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!(commands, 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.
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/vagrant/ssh/session.rb', line 121 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!(commands, 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.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/vagrant/ssh/session.rb', line 63 def exec!(commands, =nil, &block) retryable(:tries => 5, :on => [IOError, Net::SSH::Disconnect], :sleep => 1.0) do = session.open_channel do |ch| ch.exec("#{env.config.ssh.shell} -l") do |ch2, success| # Set the terminal ch2.send_data "export TERM=vt100\n" # Output the commands as if they were entered on the command line [commands].flatten.each do |command| ch2.send_data "#{command}\n" end # Remember to exit ch2.send_data "exit\n" # Setup the callbacks setup_channel_callbacks(ch2, commands, , 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.
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 117 |
# File 'lib/vagrant/ssh/session.rb', line 90 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| # This clears the screen, we want to filter it out. data.gsub!("\e[H", "") 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 55 56 57 |
# File 'lib/vagrant/ssh/session.rb', line 35 def sudo!(commands, =nil, &block) channel = session.open_channel do |ch| ch.exec("sudo -H #{env.config.ssh.shell} -l") do |ch2, success| # Set the terminal ch2.send_data "export TERM=vt100\n" # 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 |