Module: ZTK::SSH::Exec
- Included in:
- ZTK::SSH
- Defined in:
- lib/ztk/ssh/exec.rb
Overview
SSH Command Execution Functionality
Instance Method Summary (collapse)
-
- (OpenStruct#output, OpenStruct#exit) exec(command, options = {})
Executes a command on the remote host.
Instance Method Details
- (OpenStruct#output, OpenStruct#exit) exec(command, options = {})
Executes a command on the remote host.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/ztk/ssh/exec.rb', line 36 def exec(command, ={}) = OpenStruct.new(config.send(:table).merge()) .ui.logger.debug { "config=#{config.send(:table).inspect}" } .ui.logger.debug { "options=#{.send(:table).inspect}" } .ui.logger.info { "exec(#{command.inspect})" } output = "" exit_code = -1 exit_signal = nil stdout_header = false stderr_header = false begin raise_on_exceptions = [Timeout::Error] defined?(Resque) and raise_on_exceptions << Resque::TermException ZTK::RescueRetry.try( :ui => config.ui, :tries => ZTK::SSH::RESCUE_RETRY_ATTEMPTS, :raise => raise_on_exceptions, :on_retry => method(:on_retry) ) do Timeout.timeout(.timeout) do channel = ssh.open_channel do |chan| .ui.logger.debug { "Channel opened." } (.request_pty == true) and chan.request_pty do |ch, success| if success .ui.logger.debug { "PTY obtained." } else .ui.logger.warn { "Could not obtain PTY." } end end direct_log(:info) { log_header("COMMAND") } direct_log(:info) { "#{command}\n" } direct_log(:info) { log_header("OPENED", "-") } chan.exec(command) do |ch, success| success or log_and_raise(SSHError, "Could not execute '#{command}'.") ch.on_data do |c, data| if !stdout_header direct_log(:info) { log_header("STDOUT", "-") } stdout_header = true stderr_header = false end direct_log(:info) { data } .ui.stdout.print(data) unless .silence output += data .on_progress.nil? or .on_progress.call end ch.on_extended_data do |c, type, data| if !stderr_header direct_log(:warn) { log_header("STDERR", "-") } stderr_header = true stdout_header = false end direct_log(:warn) { data } .ui.stderr.print(data) unless .silence output += data .on_progress.nil? or .on_progress.call end ch.on_request("exit-status") do |c, data| exit_code = data.read_long end ch.on_request("exit-signal") do |c, data| exit_signal = data.read_long end ch.on_open_failed do |c, code, desc| .ui.logger.fatal { "Open failed! (#{code.inspect} - #{desc.inspect})" } end end end channel.wait direct_log(:info) { log_header("CLOSED") } .ui.logger.debug { "Channel closed." } end end rescue Timeout::Error => e direct_log(:fatal) { log_header("TIMEOUT") } log_and_raise(SSHError, "Session timed out after #{.timeout} seconds!") end = [ "exit_code=#{exit_code}", (exit_signal.nil? ? nil : "exit_signal=#{exit_signal} (#{EXIT_SIGNALS[exit_signal]})") ].compact.join(", ") .ui.logger.debug { } if !.ignore_exit_status && (exit_code != .exit_code) log_and_raise(SSHError, ) end OpenStruct.new(:command => command, :output => output, :exit_code => exit_code, :exit_signal => exit_signal) end |