Class: Vagrant::SSH::Session
- Inherits:
-
Object
- Object
- Vagrant::SSH::Session
- Includes:
- Util::Retryable
- Defined in:
- lib/vagrant/ssh/session.rb
Overview
A helper class which wraps around Net::SSH::Connection::Session
in order to provide basic command error checking while still
providing access to the actual session object.
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#session ⇒ Object
readonly
Returns the value of attribute session.
Instance Method Summary collapse
-
#check_exit_status(exit_status, commands, options = nil, output = nil) ⇒ Object
Checks for an erroroneous exit status and raises an exception if so.
-
#exec!(command, options = nil, &block) ⇒ Object
Executes a given command on the SSH session and blocks until the command completes.
-
#initialize(session, env) ⇒ Session
constructor
A new instance of Session.
-
#setup_channel_callbacks(channel, command, options, block) ⇒ Object
Sets up the channel callbacks to properly check exit statuses and callback on stdout/stderr.
-
#sudo!(commands, options = nil, &block) ⇒ Object
Executes a given command on the SSH session using
sudo
and blocks until the command completes. -
#test?(command) ⇒ Boolean
Executes a given command and simply returns true/false if the command succeeded or not.
Methods included from Util::Retryable
Constructor Details
#initialize(session, env) ⇒ Session
Returns a new instance of Session.
12 13 14 15 |
# File 'lib/vagrant/ssh/session.rb', line 12 def initialize(session, env) @session = session @env = env end |
Instance Attribute Details
#env ⇒ Object (readonly)
Returns the value of attribute env.
10 11 12 |
# File 'lib/vagrant/ssh/session.rb', line 10 def env @env end |
#session ⇒ Object (readonly)
Returns the value of attribute session.
9 10 11 |
# File 'lib/vagrant/ssh/session.rb', line 9 def session @session end |
Instance Method Details
#check_exit_status(exit_status, commands, options = nil, output = nil) ⇒ Object
Checks for an erroroneous exit status and raises an exception if so.
104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/vagrant/ssh/session.rb', line 104 def check_exit_status(exit_status, commands, =nil, output=nil) if exit_status != 0 output ||= '[no output]' = { :_error_class => Errors::VagrantError, :_key => :ssh_bad_exit_status, :command => [commands].flatten.join("\n"), :output => output }.merge( || {}) raise [:_error_class], end end |
#exec!(command, options = nil, &block) ⇒ Object
Executes a given command on the SSH session and blocks until
the command completes. This is an almost line for line copy of
the actual exec!
implementation, except that this
implementation also reports :exit_status
to the block if given.
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/vagrant/ssh/session.rb', line 60 def exec!(command, =nil, &block) retryable(:tries => 5, :on => IOError, :sleep => 0.5) do = session.open_channel do |channel| channel.exec(command) do |ch, success| raise "could not execute command: #{command.inspect}" unless success setup_channel_callbacks(ch, command, , block) end end .wait [:result] end end |
#setup_channel_callbacks(channel, command, options, block) ⇒ Object
Sets up the channel callbacks to properly check exit statuses and callback on stdout/stderr.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/vagrant/ssh/session.rb', line 76 def setup_channel_callbacks(channel, command, , block) = { :error_check => true }.merge( || {}) block ||= Proc.new do |ch, type, data| check_exit_status(data, command, , ch[:result]) if type == :exit_status && [:error_check] ch[:result] ||= "" ch[:result] << data if [:stdout, :stderr].include?(type) end # Output stdout data to the block channel.on_data do |ch2, data| block.call(ch2, :stdout, data) end # Output stderr data to the block channel.on_extended_data do |ch2, type, data| block.call(ch2, :stderr, data) end # Output exit status information to the block channel.on_request("exit-status") do |ch2, data| block.call(ch2, :exit_status, data.read_long) end end |
#sudo!(commands, options = nil, &block) ⇒ Object
Executes a given command on the SSH session using sudo
and
blocks until the command completes. This takes the same parameters
as #exec!. The only difference is that the command can be an
array of commands, which will be placed into the same script.
This is different than just calling #exec! with sudo
, since
this command is tailor-made to be compliant with older versions
of sudo
.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/vagrant/ssh/session.rb', line 35 def sudo!(commands, =nil, &block) channel = session.open_channel do |ch| ch.exec("sudo #{env.config.ssh.sudo_shell} -l") do |ch2, success| # Output each command as if they were entered on the command line [commands].flatten.each do |command| ch2.send_data "#{command}\n" end # Remember to exit or we'll hang! ch2.send_data "exit\n" # Setup the callbacks with our options so we get all the # stdout/stderr and error checking goodies setup_channel_callbacks(ch2, commands, , block) end end channel.wait channel[:result] end |
#test?(command) ⇒ Boolean
Executes a given command and simply returns true/false if the command succeeded or not.
19 20 21 22 23 24 25 |
# File 'lib/vagrant/ssh/session.rb', line 19 def test?(command) exec!(command) do |ch, type, data| return true if type == :exit_status && data == 0 end false end |