Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get exit status with Ruby's Net::SSH library?

Tags:

ssh

ruby

net-ssh

I have a snippet of code, simply trying to execute a script on a remote server, in the event that it fails, I'd like to make a follow-up call, imagine this:

require 'rubygems' require 'net/ssh' require 'etc'  server = 'localhost'  Net::SSH.start(server, Etc.getlogin) do |ssh|   puts (ssh.exec("true")  ? 'Exit Success' : "Exit Failure")   puts (ssh.exec("false") ? 'Exit Success' : "Exit Failure")   end 

I would expect (ignoring that stdout and stderr are printed in my contrived example) - but first line should exit with 0 which I would expect Ruby would interperate as false and display "Exit Failure" (sure, so the logic is wrong, the ternary needs to be flipped) - but the second line should exit with the opposite status, and it doesn't.

I can't even find anything in the documentation about how to do this, and I'm a little worried that I might be doing it wrong?!

like image 606
Lee Hambley Avatar asked Aug 02 '10 08:08

Lee Hambley


1 Answers

I find the following way of running processes with Net::SSH much more useful. It provides you with distinct stdout and stderr, exit code and exit signal.

require 'rubygems' require 'net/ssh' require 'etc'  server = 'localhost'  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  Net::SSH.start(server, Etc.getlogin) do |ssh|   puts ssh_exec!(ssh, "true").inspect   # => ["", "", 0, nil]    puts ssh_exec!(ssh, "false").inspect     # => ["", "", 1, nil]  end 

Hope this helps.

like image 81
flitzwald Avatar answered Nov 10 '22 13:11

flitzwald