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