Class: CloudFlock::Remote::SSH
- Inherits:
-
Object
- Object
- CloudFlock::Remote::SSH
- Defined in:
- lib/cloudflock/remote/ssh.rb,
lib/cloudflock/error.rb,
lib/cloudflock/errstr.rb,
lib/cloudflock/remote/ssh/watchdog.rb
Overview
The SSH Class wraps the tasks of logging into a host and interacting with it via SSH.
Examples
# Log into [email protected]
shell = SSH.new(host: 'host.example.com', pass: 'examplepass')
shell.puts 'ls'
Defined Under Namespace
Modules: Errstr Classes: InvalidHostname, SSHCannotConnect, Watchdog
Constant Summary collapse
- SSH_ARGUMENTS =
Public: String containing arguments to pass to ssh(1)
'-o UserKnownHostsFile=/dev/null ' \ '-o StrictHostKeyChecking=no ' \ '-o NumberOfPasswordPrompts=1 ' \ '-o ConnectTimeout=15 ' \ '-o ServerAliveInterval=30'
- NET_SSH_OPTIONS =
Public: Hash containing always-set options for Net::SSH
{ user_known_hosts_file: '/dev/null', paranoid: false }
- PROMPT =
Public: Prompt to be set on a host upon successful login.
'@@CLOUDFLOCK@@'
- HISTFILE =
Public: Absolute path to the history file to use.
'/root/.cloudflock_history'
- DEFAULT_ARGS =
Internal: Default arguments to be used for SSH session initialization.
{username: '', password: '', ssh_key: '', port: 22}
- DEFAULT_BATCH_ARGS =
Internal: Default settings for calls to #batch.
{ timeout: 30, recoverable: true }
Instance Attribute Summary collapse
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
-
#as_root(command, timeout = 30, recoverable = false) ⇒ Object
Public: Wrap query, guaranteeing that the user performing the given command is root.
-
#batch(commands) ⇒ Object
Public: Call query on a list of commands, allowing optional timeout and recoverable settings per command.
-
#hostname ⇒ Object
Public: Return the hostname of the host.
-
#initialize(args = {}) ⇒ SSH
constructor
Public: Create a new SSH object and log in to the specified host via ssh.
-
#logout! ⇒ Object
Public: Terminate the active ssh session.
-
#query(command, timeout = 30, recoverable = false, send_data = []) ⇒ Object
Public: Open a channel and execute an arbitrary command, returning any data returned over the channel.
Constructor Details
#initialize(args = {}) ⇒ SSH
Public: Create a new SSH object and log in to the specified host via ssh.
args - Hash containing arguments relating to the SSH session. (default
defined in DEFAULT_ARGS):
:hostname - String containing the address of the remote host.
:username - String containing the remote user with which to log
in. (default: '')
:password - String containing the password with which to log in.
(default: '')
:port - Fixnum specifying the port to which to connect.
(default: 22)
:ssh_key - String containing the path to an ssh private key.
(default: '')
:passphrase - The passphrase for the ssh key if applicable.
(default: '')
Raises InvalidHostname if host lookup fails. Raises LoginFailed if logging into the host fails.
59 60 61 62 63 |
# File 'lib/cloudflock/remote/ssh.rb', line 59 def initialize(args = {}) @options = sanitize_arguments(DEFAULT_ARGS.merge(args)) start_session start_keepalive_thread end |
Instance Attribute Details
#options ⇒ Object (readonly)
Returns the value of attribute options.
39 40 41 |
# File 'lib/cloudflock/remote/ssh.rb', line 39 def @options end |
Instance Method Details
#as_root(command, timeout = 30, recoverable = false) ⇒ Object
Public: Wrap query, guaranteeing that the user performing the given command is root.
command - Command to be executed. timeout - Number of seconds to allow the command to run before
terminating the channel and returning any buffer returned
so far. A value of 0 or nil will result in no timeout.
(default: 30)
recoverable - Whether a Timeout should be considered acceptable.
(default: false)
Returns a String. Raises Timeout::Error if timeout is reached.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/cloudflock/remote/ssh.rb', line 149 def as_root(command, timeout = 30, recoverable = false) return query(command, timeout, recoverable) if root? priv = 'su -' priv = 'sudo ' + priv if [:sudo] uid = ['id;logout||exit'] command = ["#{command};logout||exit"] passwordless = query(priv, timeout, true, uid) unless /uid=0/.match(passwordless) command.unshift([:root_password] + "\n") end buffer = query(priv, timeout, recoverable, command) cleanup = Regexp.new("^#{Regexp::escape(command.join)}\r\n") buffer.gsub(cleanup, '') end |
#batch(commands) ⇒ Object
Public: Call query on a list of commands, allowing optional timeout and recoverable settings per command.
commands - Array containing Hashes containing at minimum a command key.
Hash should follow the following specification:
command - Command to execute.
timeout - Timeout to specify for the call to #query.
(default: 30)
recoverable - Whether the call should be considered
recoverable if the timeout is reached.
(default: true)
Returns an Array containing results of each command.
131 132 133 134 |
# File 'lib/cloudflock/remote/ssh.rb', line 131 def batch(commands) commands.map! { |c| DEFAULT_BATCH_ARGS.merge(c) } commands.map { |c| query(c[:command], c[:timeout], c[:recoverable]) } end |
#hostname ⇒ Object
Public: Return the hostname of the host.
Returns a String.
68 69 70 |
# File 'lib/cloudflock/remote/ssh.rb', line 68 def hostname [:hostname] end |
#logout! ⇒ Object
Public: Terminate the active ssh session.
Returns nothing.
171 172 173 174 |
# File 'lib/cloudflock/remote/ssh.rb', line 171 def logout! @ssh.close @ssh = nil end |
#query(command, timeout = 30, recoverable = false, send_data = []) ⇒ Object
Public: Open a channel and execute an arbitrary command, returning any data returned over the channel.
command - Command to be executed. timeout - Number of seconds to allow the command to run before
terminating the channel and returning any buffer returned
so far. A value of 0 or nil will result in no timeout.
(default: 30)
recoverable - Whether a Timeout should be considered acceptable.
(default: false)
send_data - Array containing data to be sent to across the channel
after the command has been run. (default: [])
Returns a String. Raises Timeout::Error if timeout is reached.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/cloudflock/remote/ssh.rb', line 87 def query(command, timeout = 30, recoverable = false, send_data = []) buffer = '' running = 0 channel = @ssh.open_channel do |channel| channel.request_pty channel.exec(command) do |ch, success| ch.on_data { |_, data| buffer << data } ch.on_extended_data { |_, _, data| buffer << data } ch.send_data(send_data.join + "\n") end end Timeout::timeout(timeout) { channel.wait } buffer.strip rescue Timeout::Error raise unless recoverable channel.close buffer.strip rescue EOFError start_session retry rescue IO::EAGAINWaitReadable sleep 10 start_session retry end |