lib/remote/session.rb in remote-session-0.0.4 vs lib/remote/session.rb in remote-session-0.0.5
- old
+ new
@@ -6,11 +6,13 @@
require 'net/ssh'
require 'base64'
module Remote
class Session
- SUDO_PROMPT = 'sudo_prompt'
+ SUDO_PASSWORD_PROMPT = 'remote-session-sudo-prompt'
+ ROOT_COMMAND_PROMPT = 'remote-session-prompt#'
+ ROOT_COMMAND_PROMPT_MATCH = /#{ ROOT_COMMAND_PROMPT }$/
def self.open( host, options = {}, &block )
rs = new( host, options )
block.call rs
@@ -45,11 +47,11 @@
puts @session.exec!( command )
end
def sudo( commands )
raise "Session is closed" if @session.nil?
- commands = [ *commands ] + [ 'exit' ]
+ commands = [ *commands ]
@session.open_channel do |ch|
ch.request_pty do |ch, success|
raise "Could not obtain pty" if ! success
@@ -87,42 +89,72 @@
end
def channel_exec( ch, commands )
ch[ :commands ] = commands
- ch.exec "sudo -k -p '#{ SUDO_PROMPT }' su -" do |ch, success|
+ ch.exec "sudo -k -p '#{ SUDO_PASSWORD_PROMPT }' su -" do |ch, success|
raise "Could not execute sudo su command" if ! success
- ch.on_data( &method( :on_data ) )
+ ch.on_data &method( :handle_sudo_password_prompt )
ch.on_extended_data do |ch, type, data|
$stderr.puts data
end
end
end
- def on_data( ch, data )
- if data =~ Regexp.new( SUDO_PROMPT )
+ def handle_sudo_password_prompt( ch, data )
+ $stdout.write data
+
+ if data =~ Regexp.new( SUDO_PASSWORD_PROMPT )
ch.send_data "#{ @sudo_password }\n"
- return
+ ch.on_data &method( :set_command_prompt )
end
+ end
+ # Set the root command prompt to something we can
+ # recognise, and wait until that prompt comes back
+ def set_command_prompt( ch, data )
+ $stdout.write data
+
+ if data =~ ROOT_COMMAND_PROMPT_MATCH
+ # Got it, now we can switch so sending commands
+ ch[ :awaiting_prompt ] = false
+ ch.on_data &method( :on_data )
+ do_command ch, data
+ elsif ! ch[ :awaiting_prompt ]
+ # this is the first time through...
+ ch[ :awaiting_prompt ] = true
+ ch.send_data "export PS1='#{ ROOT_COMMAND_PROMPT }'"
+ # else: Waiting for new root prompt
+ end
+ end
+
+ def on_data( ch, data )
+ $stdout.write data
+
@prompts.each_pair do | prompt, send |
if data =~ Regexp.new( prompt )
ch.send_data "#{ send }\n"
return
end
end
- $stdout.write( data )
+ if data =~ ROOT_COMMAND_PROMPT_MATCH
+ do_command ch, data
+ end
+ end
- return if ch[ :commands ].size == 0
-
- command = ch[ :commands ].shift
- if command.is_a?( Remote::Session::Send )
- send_file_chunk( ch, command )
+ def do_command( ch, data )
+ if ch[ :commands ].size > 0
+ command = ch[ :commands ].shift
+ if command.is_a?( Remote::Session::Send )
+ send_file_chunk( ch, command )
+ else
+ ch.send_data "#{command}\n"
+ end
else
- ch.send_data "#{command}\n"
+ ch.send_data "exit\n"
end
end
def send_file_chunk( ch, send_file )
if send_file.open?