Question

How do I get stdout from the .execute method in Net-SSH-Shell

With good 'ol Net-SSH, this is easy

Net::SSH.start('host','user') do |ssh|
     puts ssh.exec! 'date'
end

Gives me Tue Jun 19 23:43:53 EDT 2012

but if I try to use a shell, I get a process object

Net::SSH.start('host','user') do |ssh|
    ssh.shell do |bash|
        output = bash.execute! 'ls'
        puts output
    end
end

Gives me #<Net::SSH::Shell::Process:0x007fc809b541d0>

I can't find anything in the sparse docs about how to get standard out easily. There is the on_output method, but that doesn't seem to do anything for me if I use the execute! method

I've also tried passing a block to .execute! like

bash.execute! 'ls' do |output|
    puts output
end

but I still get a process #<Net::SSH::Shell::Process:0x007fc809b541d0>

I need the standard out in a variable that I can use and I need an actual stateful login shell, which barebones Net-SSH doesn't do to my knowledge.

Any ideas?

Edit

Along the same ideas of @vikhyat's suggestion, I tried

 ssh.shell do |bash|
      process = bash.execute! 'ls'  do |a,b|
            # a is the process itself, b is the output
            puts [a,b]
            output = b
      end
 end

But b is always empty, even when I know the command returns results.

Was it helpful?

Solution

Have you tried doing it this way?

Net::SSH.start('host','user') do |ssh|
    ssh.shell do |bash|
        process = bash.execute! 'ls'
        process.on_output do |a, b|
          # a is the process itself, b is the output
          p [a, b]
        end
    end
end

You can have a look at the definition of Net::SSH::Process here: https://github.com/mitchellh/net-ssh-shell/blob/master/lib/net/ssh/shell/process.rb

EDIT

I think the problem lies with the ! in execute! because the following works fine for me:

require 'net/ssh'
require 'net/ssh/shell'

Net::SSH.start('students.iitmandi.ac.in', 'k_vikhyat') do |ssh|
  ssh.shell do |bash|
    process = bash.execute 'whoami'
    process.on_output do |a, b|
      p b
    end
    bash.wait!
    bash.execute! 'exit'
  end
end

I am not sure why this is the case, because it looks like execute! creates a process, runs wait! and then returns the process.

OTHER TIPS

I'm using next wrapper

def ssh_exec!(ssh, command)
    stdout_data = ""
    stderr_data = ""
    exit_code = nil
    exit_signal = nil

    ssh.open_channel do |channel|
      channel.exec(command) do |ch, success|
        unless success
          abort "FAILED: couldn't execute command (ssh.channel.exec)"
        end

        channel.on_data do |ch,data|
          stdout_data+=data
        end

        channel.on_extended_data do |ch,type,data|
          stderr_data+=data
        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
    [stdout_data, stderr_data, exit_code, exit_signal]
  end

And usage:

Net::SSH.start(@ssh_host, @ssh_user, :password => @ssh_password) do |ssh|
  result = ssh_exec! ssh, command
end

Found it sometime at SO or somewhere else, don't remember now.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top