Method: SshExec.ssh_exec!

Defined in:
lib/ssh-exec.rb

.ssh_exec!(ssh, command, options = {}) ⇒ OpenStruct

Execute the given command using the given ssh object and capture its standard output, standard error, and exit status. The implementation is based on this StackOveflow answer.

Parameters:

  • ssh

    the Net::SSH shell to run the command in

  • options (Hash) (defaults to: {})

    optional settings: echo_stdout - whether to echo standard output from the subcommand, echo_stderr - whether to echo standard error from the subcommand

Returns:

  • (OpenStruct)

    a struct containing stdout, stderr, exit_status, and exit_signal



30
31
32
33
34
35
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
# File 'lib/ssh-exec.rb', line 30

def self.ssh_exec!(ssh, command, options = {})
  options = options.clone
  echo_stdout = options[:echo_stdout]
  echo_stderr = options[:echo_stderr]
  raise "Invalid options: #{options}" unless options.empty?

  stdout_data = ""
  stderr_data = ""
  exit_code = nil
  exit_signal = nil
  ssh.open_channel do |channel|
    channel.exec(command) do |ch, success|
      unless success
        raise "FAILED: couldn't execute command #{command}"
      end
      channel.on_data do |ch, data|
        stdout_data += data
        $stdout.write(data) if echo_stdout
      end

      channel.on_extended_data do |ch, type, data|
        stderr_data += data
        $stderr.write(data) if echo_stderr
      end

      channel.on_request("exit-status") do |ch, data|
        exit_code = data.read_long
      end

      channel.on_request("exit-signal") do |ch, data|
        exit_signal = data.read_long
      end
    end
  end
  ssh.loop
  OpenStruct.new(
    :stdout => stdout_data,
    :stderr => stderr_data,
    :exit_status => exit_code,
    :exit_signal => exit_signal
  )
end