Overview
The debug gem provides interactive debugging capabilities for Ruby applications through configurable breakpoints, remote debugging, and session management. Ruby integrates debug gem configuration through environment variables, configuration files, and runtime settings that control debugging behavior, output formatting, and connection parameters.
The primary configuration interface centers around the RUBY_DEBUG_*
environment variables and the .rdbgrc
configuration file. The debug gem reads these settings during initialization to establish debugging sessions, configure output streams, and set up remote debugging connections.
# Basic debug gem initialization with configuration
require 'debug'
# Configuration is read automatically on require
# Environment variables take precedence over config files
binding.b # Creates breakpoint with current configuration
Debug configuration affects several core components: the debugger protocol handler, output formatters, breakpoint managers, and remote connection handlers. Each component reads specific configuration parameters during startup and runtime.
# Configuration impacts multiple debugging aspects
ENV['RUBY_DEBUG_PORT'] = '12345'
ENV['RUBY_DEBUG_HOST'] = '0.0.0.0'
ENV['RUBY_DEBUG_OPEN'] = 'true'
require 'debug/open' # Respects configuration settings
The debug gem configuration system supports both global settings that affect all debugging sessions and per-session settings that can be modified during debugging. Configuration validation occurs during gem initialization, with invalid settings generating warnings rather than errors.
# Configuration validation example
ENV['RUBY_DEBUG_LOG_LEVEL'] = 'invalid_level'
require 'debug'
# Warning: invalid log level, using 'warn' instead
Basic Usage
Debug gem configuration begins with environment variables that control fundamental debugging behavior. The RUBY_DEBUG
environment variable serves as the primary activation switch, accepting boolean values or specific debugging modes.
# Enable debugging globally
ENV['RUBY_DEBUG'] = '1'
require 'debug'
# Program execution pauses at first binding.b
puts "Application starting"
binding.b # Debugger activates here
puts "Application continuing"
The .rdbgrc
configuration file provides persistent settings across debugging sessions. Ruby searches for this file in the current directory, home directory, and system-wide locations, applying settings in order of precedence.
# .rdbgrc configuration file example
# Set default log level
set log-level info
# Configure output formatting
set show-src-lines 10
set show-frames 5
# Set up remote debugging
set port 12345
set host localhost
Port and host configuration enables remote debugging scenarios where the debugger runs on a different machine or container. The debug gem validates network settings and establishes connections based on these parameters.
# Remote debugging configuration
ENV['RUBY_DEBUG_PORT'] = '9001'
ENV['RUBY_DEBUG_HOST'] = '192.168.1.100'
ENV['RUBY_DEBUG_SOCK_PATH'] = '/tmp/ruby-debug.sock'
require 'debug/open_nonstop' # Opens remote session immediately
Log level configuration controls debugging output verbosity, affecting both console output and log file generation. Valid levels include fatal
, error
, warn
, info
, and debug
, with each level including messages from higher severity levels.
# Configure logging output
ENV['RUBY_DEBUG_LOG_LEVEL'] = 'debug'
ENV['RUBY_DEBUG_LOG_FILE'] = '/var/log/ruby-debug.log'
require 'debug'
# All debugging operations generate detailed logs
Advanced Usage
Complex debugging scenarios require sophisticated configuration patterns that combine multiple settings and conditional activation. Environment-based configuration allows different debugging behavior across development, testing, and staging environments.
# Environment-specific debug configuration
class DebugConfig
def self.setup
case ENV['RAILS_ENV']
when 'development'
ENV['RUBY_DEBUG'] = '1'
ENV['RUBY_DEBUG_LOG_LEVEL'] = 'debug'
ENV['RUBY_DEBUG_SHOW_SRC_LINES'] = '15'
when 'test'
ENV['RUBY_DEBUG'] = '0' # Disable interactive debugging
ENV['RUBY_DEBUG_LOG_LEVEL'] = 'error'
when 'staging'
ENV['RUBY_DEBUG_PORT'] = '9229'
ENV['RUBY_DEBUG_HOST'] = '0.0.0.0'
ENV['RUBY_DEBUG_OPEN'] = 'true'
end
end
end
DebugConfig.setup
require 'debug'
Configuration inheritance and override patterns enable modular debugging setups where base configurations are extended for specific scenarios. The debug gem respects configuration layering with environment variables taking precedence over configuration files.
# Hierarchical configuration setup
module DebugSetup
BASE_CONFIG = {
'RUBY_DEBUG_LOG_LEVEL' => 'info',
'RUBY_DEBUG_SHOW_FRAMES' => '10',
'RUBY_DEBUG_SHOW_SRC_LINES' => '5'
}
REMOTE_CONFIG = BASE_CONFIG.merge({
'RUBY_DEBUG_PORT' => '12345',
'RUBY_DEBUG_HOST' => 'localhost',
'RUBY_DEBUG_OPEN' => 'true'
})
def self.apply_config(config_hash)
config_hash.each { |key, value| ENV[key] = value }
require 'debug/start'
end
end
# Apply remote debugging configuration
DebugSetup.apply_config(DebugSetup::REMOTE_CONFIG)
Dynamic configuration modification during runtime allows debugging behavior adjustment without restarting applications. The debug gem provides configuration commands that modify settings within active debugging sessions.
# Runtime configuration modification
require 'debug'
def configure_debug_session
binding.b
# Within debug session:
# config set show-src-lines 20
# config set log-level debug
# config list # Show current configuration
end
# Configuration persists for session duration
configure_debug_session
Multi-process debugging configuration requires coordination between parent and child processes to avoid port conflicts and ensure proper debugging session management.
# Multi-process debug configuration
class MultiProcessDebug
def self.configure_fork_debugging
parent_port = ENV['RUBY_DEBUG_PORT']&.to_i || 12345
# Configure parent process
ENV['RUBY_DEBUG_PORT'] = parent_port.to_s
ENV['RUBY_DEBUG_OPEN'] = 'true'
require 'debug'
# Fork with different debug port
pid = fork do
ENV['RUBY_DEBUG_PORT'] = (parent_port + 1).to_s
require 'debug/start'
# Child process debugging code
binding.b
puts "Child process: #{Process.pid}"
end
# Parent continues with original configuration
binding.b
puts "Parent process: #{Process.pid}"
Process.wait(pid)
end
end
Error Handling & Debugging
Debug gem configuration errors manifest in various forms, from invalid parameter values to network connection failures. The debug gem implements defensive configuration parsing that continues operation with fallback values when encountering invalid settings.
# Configuration error handling patterns
module DebugErrorHandling
def self.validate_and_configure
begin
# Invalid port configuration
ENV['RUBY_DEBUG_PORT'] = 'invalid_port'
require 'debug/open'
rescue ArgumentError => e
warn "Debug configuration error: #{e.message}"
# Falls back to default port 12345
ENV['RUBY_DEBUG_PORT'] = '12345'
require 'debug/open'
end
end
def self.handle_connection_failures
ENV['RUBY_DEBUG_HOST'] = '192.168.999.999' # Invalid IP
ENV['RUBY_DEBUG_PORT'] = '9001'
begin
require 'debug/open'
rescue Errno::ECONNREFUSED, SocketError => e
puts "Remote debugging unavailable: #{e.message}"
# Switch to local debugging
ENV.delete('RUBY_DEBUG_HOST')
ENV.delete('RUBY_DEBUG_PORT')
require 'debug'
end
end
end
Configuration file parsing errors require special handling since the debug gem reads .rdbgrc
files during initialization. Syntax errors or invalid commands in configuration files generate warnings but do not prevent debugging session startup.
# Configuration file error detection
class RdbgrcValidator
def self.validate_config_file(path)
return unless File.exist?(path)
invalid_lines = []
File.readlines(path).each_with_index do |line, index|
line = line.strip
next if line.empty? || line.start_with?('#')
unless valid_config_line?(line)
invalid_lines << "Line #{index + 1}: #{line}"
end
end
unless invalid_lines.empty?
warn "Invalid .rdbgrc configuration:"
invalid_lines.each { |line| warn " #{line}" }
end
end
private
def self.valid_config_line?(line)
# Basic validation for common configuration commands
line.match?(/^set\s+\w+/) || line.match?(/^source\s+/)
end
end
# Validate before loading debug gem
RdbgrcValidator.validate_config_file('.rdbgrc')
require 'debug'
Network debugging configuration failures often occur in containerized or networked environments where specified hosts or ports become unavailable. Implementing fallback mechanisms ensures debugging capabilities remain functional despite network issues.
# Network fallback configuration
module NetworkDebugFallback
FALLBACK_PORTS = [12345, 12346, 12347, 12348, 12349]
def self.configure_with_fallback
FALLBACK_PORTS.each do |port|
ENV['RUBY_DEBUG_PORT'] = port.to_s
begin
require 'debug/open'
puts "Debug server started on port #{port}"
return true
rescue Errno::EADDRINUSE
puts "Port #{port} in use, trying next port"
next
rescue => e
puts "Failed to start debug server on port #{port}: #{e.message}"
next
end
end
warn "All fallback ports failed, switching to local debugging"
ENV.delete('RUBY_DEBUG_PORT')
ENV.delete('RUBY_DEBUG_HOST')
require 'debug'
false
end
end
Production Patterns
Production debugging configuration requires careful balance between debugging capabilities and security concerns. Debug gem settings in production environments should minimize performance impact while providing necessary troubleshooting functionality.
# Production-safe debug configuration
class ProductionDebugConfig
def self.setup
return unless production_debugging_enabled?
# Restrict debugging to specific conditions
ENV['RUBY_DEBUG'] = '1' if emergency_debugging?
ENV['RUBY_DEBUG_LOG_LEVEL'] = 'error'
ENV['RUBY_DEBUG_LOG_FILE'] = '/var/log/app/debug.log'
# Secure remote debugging configuration
if remote_debugging_required?
ENV['RUBY_DEBUG_HOST'] = '127.0.0.1' # Localhost only
ENV['RUBY_DEBUG_PORT'] = secure_port.to_s
ENV['RUBY_DEBUG_SOCK_PATH'] = '/tmp/ruby-debug-prod.sock'
end
require 'debug'
end
private
def self.production_debugging_enabled?
ENV['ENABLE_PRODUCTION_DEBUG'] == 'true'
end
def self.emergency_debugging?
File.exist?('/tmp/emergency_debug')
end
def self.remote_debugging_required?
ENV['REMOTE_DEBUG_SESSION'] == 'active'
end
def self.secure_port
# Use application-specific port range
base_port = 20000
base_port + (Process.pid % 1000)
end
end
Docker and container debugging configuration requires special consideration for network interfaces and volume mounting to ensure debugging sessions remain accessible from host systems.
# Container debugging configuration
class ContainerDebugSetup
def self.configure_for_docker
# Configure for container networking
ENV['RUBY_DEBUG_HOST'] = '0.0.0.0' # Accept external connections
ENV['RUBY_DEBUG_PORT'] = ENV['DEBUG_PORT'] || '9229'
# Use volume-mounted socket for IPC debugging
socket_path = ENV['DEBUG_SOCKET_PATH'] || '/debug/ruby-debug.sock'
ENV['RUBY_DEBUG_SOCK_PATH'] = socket_path
# Ensure socket directory exists
FileUtils.mkdir_p(File.dirname(socket_path))
# Configure logging for container output
ENV['RUBY_DEBUG_LOG_LEVEL'] = ENV['DEBUG_LOG_LEVEL'] || 'info'
ENV['RUBY_DEBUG_LOG_FILE'] = '/proc/1/fd/1' # Container stdout
require 'debug/open_nonstop'
end
def self.health_check
# Verify debugging endpoint accessibility
host = ENV['RUBY_DEBUG_HOST']
port = ENV['RUBY_DEBUG_PORT']
return false unless host && port
begin
socket = TCPSocket.new(host, port.to_i)
socket.close
true
rescue
false
end
end
end
Load balancer and proxy configuration for debug sessions requires coordination with infrastructure components to ensure debugging traffic reaches the correct application instances.
# Load balancer debug configuration
module LoadBalancerDebugConfig
def self.setup_with_instance_routing
instance_id = ENV['INSTANCE_ID'] || Socket.gethostname
base_port = ENV['BASE_DEBUG_PORT']&.to_i || 9200
# Calculate instance-specific debug port
instance_hash = instance_id.hash.abs
debug_port = base_port + (instance_hash % 100)
ENV['RUBY_DEBUG_PORT'] = debug_port.to_s
ENV['RUBY_DEBUG_HOST'] = '0.0.0.0'
# Register debug endpoint with service discovery
register_debug_endpoint(instance_id, debug_port)
require 'debug/open'
end
def self.register_debug_endpoint(instance_id, port)
# Register with load balancer or service mesh
registration_data = {
service: 'ruby-debug',
instance: instance_id,
port: port,
health_check: "/debug/health"
}
# Implementation depends on service discovery system
puts "Debug endpoint: #{instance_id}:#{port}"
end
end
Common Pitfalls
Debug gem configuration creates several categories of common mistakes that can compromise debugging effectiveness or application security. Port conflicts represent one of the most frequent configuration issues, particularly in development environments running multiple applications.
# Port conflict resolution
class DebugPortManager
@used_ports = Set.new
def self.allocate_port(preferred_port = nil)
preferred_port ||= 12345
# Check if preferred port is available
if preferred_port && !port_in_use?(preferred_port)
@used_ports.add(preferred_port)
return preferred_port
end
# Find next available port
(12345..12355).each do |port|
unless port_in_use?(port)
@used_ports.add(port)
return port
end
end
raise "No available debug ports in range"
end
def self.port_in_use?(port)
begin
server = TCPServer.new('localhost', port)
server.close
false
rescue Errno::EADDRINUSE
true
end
end
end
# Safe port allocation
debug_port = DebugPortManager.allocate_port
ENV['RUBY_DEBUG_PORT'] = debug_port.to_s
require 'debug/open'
Configuration file precedence confusion occurs when developers expect certain settings to take effect but environment variables override configuration file values. Understanding precedence order prevents debugging session misconfigurations.
# Configuration precedence demonstration
class ConfigPrecedenceIssue
def self.demonstrate_problem
# Create .rdbgrc with specific settings
File.write('.rdbgrc', <<~CONFIG)
set log-level debug
set port 9001
set show-src-lines 20
CONFIG
# Environment variables override file settings
ENV['RUBY_DEBUG_LOG_LEVEL'] = 'error' # Overrides 'debug' from file
ENV['RUBY_DEBUG_PORT'] = '9002' # Overrides '9001' from file
# show-src-lines uses file setting (no env var override)
require 'debug'
# Result: log-level=error, port=9002, show-src-lines=20
puts "Effective configuration may differ from .rdbgrc"
end
def self.show_effective_config
# Display actual configuration being used
config_sources = {
log_level: ENV['RUBY_DEBUG_LOG_LEVEL'] || 'from .rdbgrc',
port: ENV['RUBY_DEBUG_PORT'] || 'from .rdbgrc',
src_lines: ENV['RUBY_DEBUG_SHOW_SRC_LINES'] || 'from .rdbgrc'
}
puts "Effective debug configuration:"
config_sources.each { |key, value| puts " #{key}: #{value}" }
end
end
Security vulnerabilities in production debug configuration often stem from overly permissive network settings or inadequate access controls. Debug interfaces exposed to public networks create significant security risks.
# Security anti-patterns and corrections
module DebugSecurityPitfalls
# DANGEROUS: Exposes debug interface to all networks
def self.insecure_configuration
ENV['RUBY_DEBUG_HOST'] = '0.0.0.0'
ENV['RUBY_DEBUG_PORT'] = '12345'
ENV['RUBY_DEBUG_OPEN'] = 'true'
# This allows anyone to connect and debug the application
end
# SECURE: Restricts debug interface appropriately
def self.secure_configuration
# Only bind to localhost in production
if ENV['RAILS_ENV'] == 'production'
ENV['RUBY_DEBUG_HOST'] = '127.0.0.1'
# Use Unix socket instead of network port
ENV['RUBY_DEBUG_SOCK_PATH'] = '/tmp/ruby-debug-secure.sock'
File.chmod(0600, '/tmp/ruby-debug-secure.sock') if File.exist?('/tmp/ruby-debug-secure.sock')
# Require authentication token
ENV['RUBY_DEBUG_AUTH_TOKEN'] = SecureRandom.hex(32)
end
end
def self.validate_production_safety
if ENV['RAILS_ENV'] == 'production'
dangerous_settings = []
dangerous_settings << "Host set to 0.0.0.0" if ENV['RUBY_DEBUG_HOST'] == '0.0.0.0'
dangerous_settings << "No authentication configured" unless ENV['RUBY_DEBUG_AUTH_TOKEN']
dangerous_settings << "Using network port in production" if ENV['RUBY_DEBUG_PORT'] && !ENV['RUBY_DEBUG_SOCK_PATH']
unless dangerous_settings.empty?
warn "SECURITY WARNING: Dangerous debug configuration detected:"
dangerous_settings.each { |warning| warn " - #{warning}" }
end
end
end
end
Memory leaks from debug session configuration occur when debugging remains enabled in long-running processes or when debug sessions accumulate without proper cleanup.
# Memory leak prevention in debug configuration
class DebugMemoryManagement
def self.configure_with_cleanup
# Set memory limits for debug sessions
ENV['RUBY_DEBUG_MAX_SESSIONS'] = '3'
ENV['RUBY_DEBUG_SESSION_TIMEOUT'] = '3600' # 1 hour
# Configure automatic cleanup
at_exit do
cleanup_debug_resources
end
# Trap signals to ensure cleanup
Signal.trap('TERM') do
cleanup_debug_resources
exit(0)
end
require 'debug'
end
def self.cleanup_debug_resources
# Close any open debug sessions
ObjectSpace.each_object(TCPServer) do |server|
server.close if server.addr[1] == ENV['RUBY_DEBUG_PORT']&.to_i
rescue
# Ignore cleanup errors
end
# Remove debug socket files
socket_path = ENV['RUBY_DEBUG_SOCK_PATH']
File.unlink(socket_path) if socket_path && File.exist?(socket_path)
end
end
Reference
Environment Variables
Variable | Type | Default | Description |
---|---|---|---|
RUBY_DEBUG |
Boolean/String | false |
Enables debug gem functionality |
RUBY_DEBUG_PORT |
Integer | 12345 |
Network port for remote debugging |
RUBY_DEBUG_HOST |
String | localhost |
Host interface for remote debugging |
RUBY_DEBUG_SOCK_PATH |
String | None | Unix socket path for IPC debugging |
RUBY_DEBUG_LOG_LEVEL |
String | warn |
Logging verbosity level |
RUBY_DEBUG_LOG_FILE |
String | None | Log file path for debug output |
RUBY_DEBUG_OPEN |
Boolean | false |
Auto-open debug session on startup |
RUBY_DEBUG_SHOW_SRC_LINES |
Integer | 10 |
Source code lines to display |
RUBY_DEBUG_SHOW_FRAMES |
Integer | 2 |
Stack frame count to display |
RUBY_DEBUG_USE_SHORT_PATH |
Boolean | false |
Show shortened file paths |
RUBY_DEBUG_NO_COLOR |
Boolean | false |
Disable color output |
RUBY_DEBUG_NO_SIGINT_HOOK |
Boolean | false |
Disable SIGINT handling |
RUBY_DEBUG_INIT_SCRIPT |
String | None | Initialization script path |
RUBY_DEBUG_HISTORY_FILE |
String | ~/.rdbg_history |
Command history file |
RUBY_DEBUG_SAVE_HISTORY |
Boolean | true |
Save command history |
Configuration File Commands
Command | Parameters | Description |
---|---|---|
set log-level LEVEL |
fatal, error, warn, info, debug | Set logging verbosity |
set port NUMBER |
Integer (1024-65535) | Set remote debugging port |
set host ADDRESS |
IP address or hostname | Set remote debugging host |
set show-src-lines NUMBER |
Integer (1-100) | Set source line display count |
set show-frames NUMBER |
Integer (1-50) | Set stack frame display count |
set use-short-path BOOL |
true, false | Enable shortened path display |
set no-color BOOL |
true, false | Disable color output |
set save-history BOOL |
true, false | Enable command history saving |
source FILE |
File path | Load additional configuration file |
Require Variants
Require Statement | Behavior |
---|---|
require 'debug' |
Load debug gem with standard configuration |
require 'debug/start' |
Initialize debug gem and start session |
require 'debug/open' |
Open remote debugging immediately |
require 'debug/open_nonstop' |
Open remote debugging without stopping execution |
require 'debug/prelude' |
Load debug gem early in boot process |
Log Levels
Level | Numeric Value | Output Includes |
---|---|---|
fatal |
4 | Fatal errors only |
error |
3 | Fatal and error messages |
warn |
2 | Fatal, error, and warning messages |
info |
1 | Fatal, error, warning, and info messages |
debug |
0 | All messages including debug output |
Configuration Precedence
- Environment variables (highest priority)
.rdbgrc
in current directory.rdbgrc
in home directory- System-wide configuration files
- Default gem settings (lowest priority)
Common Port Ranges
Range | Purpose |
---|---|
12345-12355 |
Default debug gem ports |
9229-9239 |
Node.js inspector compatible ports |
20000-21000 |
Production debug port range |
30000-31000 |
Container debug port range |
Socket File Locations
Path | Usage |
---|---|
/tmp/ruby-debug.sock |
Development debugging |
/var/run/ruby-debug.sock |
System service debugging |
/debug/ruby-debug.sock |
Container volume debugging |
~/.ruby-debug.sock |
User-specific debugging |