Class: LiveConsole

Inherits:
Object
  • Object
show all
Includes:
Socket::Constants
Defined in:
lib/live_console.rb

Overview

LiveConsole provides a socket that can be connected to via netcat or telnet to use to connect to an IRB session inside a running process. It creates a thread that listens on the specified address/port or Unix Domain Socket path, and presents connecting clients with an IRB shell. Using this, you can execute code on a running instance of a Ruby process to inspect the state or even patch code on the fly. There is currently no readline support.

Defined Under Namespace

Modules: IOMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io_method, opts = {}) ⇒ LiveConsole

call-seq: # Bind a LiveConsole to localhost:3030 (only allow clients on this # machine to connect): LiveConsole.new :socket, :port => 3030 # Accept connections from anywhere on port 3030. Ridiculously insecure: LiveConsole.new(:socket, :port => 3030, :host => ‘0.0.0.0’) # Use a Unix Domain Socket (which is more secure) instead: LiveConsole.new(:unix_socket, :path => ‘/tmp/my_liveconsole.sock’,

:mode => 0600, :uid => Process.uid, :gid => Process.gid)

# By default, the mode is 0600, and the uid and gid are those of the # current process. These three options are for the file’s permissions. # You can also supply a binding for IRB’s toplevel: LiveConsole.new(:unix_socket, :path => “/tmp/live_console_#Process.pid.sock”, :bind => binding)

Creates a new LiveConsole. You must next call LiveConsole#start when you want to spawn the thread to accept connections and start the console.



41
42
43
44
45
46
47
48
49
# File 'lib/live_console.rb', line 41

def initialize(io_method, opts = {})
	self.io_method = io_method.to_sym
	self.bind = opts.delete :bind
	unless IOMethods::List.include?(self.io_method)
		raise ArgumentError, "Unknown IO method: #{io_method}" 
	end

	init_io opts
end

Instance Attribute Details

#bindObject

Returns the value of attribute bind.



21
22
23
# File 'lib/live_console.rb', line 21

def bind
  @bind
end

#ioObject

Returns the value of attribute io.



21
22
23
# File 'lib/live_console.rb', line 21

def io
  @io
end

#io_methodObject

Returns the value of attribute io_method.



21
22
23
# File 'lib/live_console.rb', line 21

def io_method
  @io_method
end

#threadObject

Returns the value of attribute thread.



21
22
23
# File 'lib/live_console.rb', line 21

def thread
  @thread
end

Instance Method Details

#restartObject

Restarts. Useful for binding changes. Return value is the same as for LiveConsole#start.



102
103
104
105
106
107
108
109
# File 'lib/live_console.rb', line 102

def restart
	r = lambda { stop; start }
	if thread == Thread.current
		Thread.new &r # Leaks a thread, but works.
	else
		r.call
	end
end

#startObject

LiveConsole#start spawns a thread to listen for, accept, and provide an IRB console to new connections. If a thread is already running, this method simply returns false; otherwise, it returns the new thread.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/live_console.rb', line 54

def start
	if thread 
		if thread.alive?
			return false
		else
			thread.join
			self.thread = nil
		end
	end

	self.thread = Thread.new { 
		loop {
			Thread.pass
			if io.start
				irb_io = GenericIOMethod.new io.raw_input, io.raw_output
				begin
					IRB.start_with_io(irb_io, bind)
				rescue Errno::EPIPE => e
					io.stop
				end
			end
		}
	}
	thread
end

#stopObject

Ends the running thread, if it exists. Returns true if a thread was running, false otherwise.



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/live_console.rb', line 82

def stop
	if thread
		if thread == Thread.current
			self.thread = nil
			Thread.current.exit!
		end

		thread.exit
		if thread.join(0.1).nil?
			thread.exit!
		end
		self.thread = nil
		true
	else
		false
	end
end