0

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.

wmarbut
  • 4,595
  • 7
  • 42
  • 72

2 Answers2

4

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.

wmarbut
  • 4,595
  • 7
  • 42
  • 72
vikhyat
  • 1,544
  • 1
  • 10
  • 9
  • Unfortunately, I have. The block passed to `.on_output` never gets called. Thanks though – wmarbut Jun 20 '12 at 13:13
  • I made a minor edit to your revised answer to include `bash.wait!` and `bash.execute! 'exit'`, but this was the ticket. Thanks! – wmarbut Jun 20 '12 at 15:05
1

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.

Ribtoks
  • 6,634
  • 1
  • 25
  • 37
  • I tried using channels with code from both http://net-ssh.github.com/ssh/v2/api/classes/Net/SSH/Connection/Channel.html and http://www.jayway.com/2012/01/12/capistrano-and-netssh-with-login-shell/, but didn't have any luck getting a real login shell... Thanks for your response though! – wmarbut Jun 20 '12 at 15:10
  • Try using my approach.. It's working! If it doesn't, write your errors.. Maybe it's something else blocking your ssh.. Firewall, I don't know. – Ribtoks Jun 20 '12 at 17:04
  • Will do, and I'll post results when I get that done. Always good to have more than one good way of doing things. It will probably be tomorrow before I have a chance. Thanks! – wmarbut Jun 21 '12 at 04:20