class Expect::SSH
An SSH
Accessor with expect-like behaviors. See also Expect::Behavior
.
Attributes
auth_methods[R]
:Required methods to be created by the class mixing Expect::Behaviors :
#exp_process - should do one iteration of handle input and append buffer #exp_buffer - provide the current buffer contents and empty it
Public Class Methods
new(hostname, username, port: 22, password: nil, ignore_known_hosts: false, key_file: nil, logout_command: "exit", wait_interval_sec: 0.1, log_level: Logger::WARN)
click to toggle source
# File lib/expect/ssh.rb, line 19 def initialize(hostname, username, # keyword args follow port: 22, password: nil, # password for login ignore_known_hosts: false, # ignore host key mismatches? key_file: nil, # path to private key file logout_command: "exit", # command to exit/logout SSH session on remote host wait_interval_sec: 0.1, # process interval log_level: Logger::WARN) @hostname = hostname @username = username @port = port @password = password @ignore_known_hosts = ignore_known_hosts @key_file = key_file @logout_command = logout_command @wait_interval_sec = wait_interval_sec @auth_methods = ['none', 'publickey', 'password'] @ssh = nil @logger = Logger.new($stdout) @logger.level = log_level if log_level @receive_buffer = '' end
Public Instance Methods
exp_buffer()
click to toggle source
exp_buffer
- provide the current buffer contents and empty it
# File lib/expect/ssh.rb, line 84 def exp_buffer result = @receive_buffer @receive_buffer = '' result end
exp_process()
click to toggle source
exp_process
- should do one iteration of handle input and append buffer
# File lib/expect/ssh.rb, line 92 def exp_process sleep(@wait_sec.to_f) @ssh.process(0) end
send_data(command)
click to toggle source
Transmit the contents of command
using the SSH
@channel
# File lib/expect/ssh.rb, line 45 def send_data(command) @logger.debug("[Expect::SSH##{__method__}] [@hostname=#{@hostname}] [command=#{command}]") command += "\n" unless command.end_with?("\n") @channel.send_data(command) end
start()
click to toggle source
Initiate SSH
connection
# File lib/expect/ssh.rb, line 53 def start $stdout.puts( "[Expect::SSH##{__method__}] [@hostname=#{@hostname}] [@username=#{@username}] [options=#{options}]" ) @ssh = Net::SSH.start(@hostname, @username, options) raise(RuntimeError, "[Expect::SSH##{__method__}]: SSH Start Failed") unless @ssh @channel = request_channel_pty_shell end
stop()
click to toggle source
Close SSH
connection
# File lib/expect/ssh.rb, line 64 def stop @logger.debug("[Expect::SSH##{__method__}]: Closing Channel") @channel.send_data(@logout_command + "\n") @channel.close begin # A net-ssh quirk is that if you send a graceful close but you don't send an exit, it'll hang forever # ...see also: http://stackoverflow.com/questions/25576454/ruby-net-ssh-script-not-closing # I send an exit but just in case, also force the shutdown if it doesn't happen in 1 second. #NotPatient Timeout::timeout(1) do @logger.debug("[Expect::SSH##{__method__}]: Closing Session") @ssh.close end rescue Timeout::Error @logger.debug("[Expect::SSH##{__method__}]: FORCE Closing Session") @ssh.shutdown! end end
Private Instance Methods
options()
click to toggle source
Construct the options hash to feed Net::SSH
# File lib/expect/ssh.rb, line 147 def options override_options = { :auth_methods => auth_methods, :logger => @logger, :port => @port, } override_options[:keys] = [@key_file] if @key_file override_options[:user_known_hosts_file] = '/dev/null' if @ignore_known_hosts override_options[:password] = @password if @password Net::SSH.configuration_for(@host).merge(override_options) end
register_callbacks(channel)
click to toggle source
# File lib/expect/ssh.rb, line 128 def register_callbacks(channel) @logger.debug("[Expect::SSH##{__method__}]: Registering Callbacks") channel.on_data do |_ch, data| @logger.debug("[Expect::SSH] [on_data=#{data}]") @receive_buffer << data false end channel.on_extended_data do |_ch, type, data| @logger.debug("[Expect::SSH] [on_extended_data=#{data}]") @receive_buffer << data if type == 1 false end channel.on_close do @logger.debug("[Expect::SSH]: Close Channel") end end
request_channel_pty_shell()
click to toggle source
Sets up the channel, pty, and shell. Configures callbacks for handling incoming data.
# File lib/expect/ssh.rb, line 104 def request_channel_pty_shell channel = @ssh.open_channel do |channel| request_pty(channel) request_shell(channel) register_callbacks(channel) end @logger.debug("[Expect::SSH##{__method__}] complete") channel end
request_pty(channel)
click to toggle source
# File lib/expect/ssh.rb, line 114 def request_pty(channel) @logger.debug("[Expect::SSH##{__method__}]: Requesting PTY") channel.request_pty do |_ch, success| raise(RuntimeError, "[Expect::SSH##{__method__}]: Unable to get PTY") unless success end end
request_shell(channel)
click to toggle source
# File lib/expect/ssh.rb, line 121 def request_shell(channel) @logger.debug("[Expect::SSH##{__method__}]: Requesting Shell") channel.send_channel_request("shell") do |_ch, success| raise(RuntimeError, "[Expect::SSH##{__method__}]: Unable to get SHELL") unless success end end