lib/remote/session.rb in remote-session-0.0.1 vs lib/remote/session.rb in remote-session-0.0.2

- old
+ new

@@ -1,6 +1,7 @@ require 'remote/session/version' +require 'net/sftp' require 'net/ssh' module Remote class Session SUDO_PROMPT = 'sudo_prompt' @@ -11,66 +12,99 @@ block.call rs rs.close end - attr_accessor :host, :user, :password, :options + attr_accessor :host + attr_accessor :username + attr_accessor :password + attr_accessor :port + attr_accessor :private_key + attr_accessor :prompts + attr_accessor :session def initialize( host, options = {} ) - @host = host - @options = options.clone - @user = @options.delete( :user ) || ENV[ 'USER' ] - @password = @options.delete( :password ) + @session = nil + @host = host + @username = options[ :username ] || ENV[ 'USER' ] + @password = options[ :password ] + @port = options[ :port ] + @private_key = options[ :private_key ] + @prompts = options[ :prompts ] || {} + @sudo_password = options[ :sudo_password ] + connect end def run( command ) raise "Session is closed" if @session.nil? puts "@#{ @host }: #{ command }" puts @session.exec!( command ) end - def sudo( command, prompts = {} ) + def sudo( command ) raise "Session is closed" if @session.nil? puts "@#{ @host }: sudo #{ command }" @session.open_channel do |ch| ch.request_pty do |ch, success| raise "Could not obtain pty" if ! success - channel_exec ch, command, prompts + channel_exec ch, command end end @session.loop end def close @session.close @session = nil end + def sudo_put( remote_path, &block ) + temp_path = "/tmp/remote-session.#{ Time.now.to_f }" + run "mkdir #{ temp_path }" + run "chmod 0700 #{ temp_path }" + + temp_file = File.join( temp_path, File.basename( remote_path ) ) + put temp_file, &block + + sudo "cp -f #{ temp_file } #{ remote_path }" + run "rm -rf #{ temp_path }" + end + + def put( remote_path, &block ) + sftp = Net::SFTP::Session.new( @session ).connect! + sftp.file.open( remote_path, 'w' ) do |f| + f.puts block.call + end + sftp.close_channel + end + private def ssh_options s = {} - s[ :password ] = @password if @password + s[ :password ] = @password if @password + s[ :keys ] = [ @private_key ] if @private_key + s[ :port ] = @port if @port s end def connect - @session = Net::SSH.start( @host, @user, ssh_options ) + @session = Net::SSH.start( @host, @username, ssh_options ) end - def channel_exec( ch, command, prompts ) + def channel_exec( ch, command ) ch.exec "sudo -p '#{ SUDO_PROMPT }' #{ command }" do |ch, success| raise "Could not execute sudo command: #{ command }" if ! success ch.on_data do | ch, data | if data =~ Regexp.new( SUDO_PROMPT ) - ch.send_data "#{ @options[ :sudo_password ] }\n" + ch.send_data "#{ @sudo_password }\n" else prompt_matched = false - prompts.each_pair do | prompt, send | + @prompts.each_pair do | prompt, send | if data =~ Regexp.new( prompt ) ch.send_data "#{ send }\n" prompt_matched = true end end