para - ¿Cómo obtener el estado de salida con la biblioteca Ruby''s Net:: SSH?
tags for likes 2017 (2)
Tengo un fragmento de código, simplemente intento ejecutar un script en un servidor remoto, en el caso de que falle, me gustaría hacer una llamada de seguimiento, imagina esto:
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
Yo esperaría (ignorando que stdout y stderr están impresos en mi ejemplo artificial) - pero la primera línea debería salir con 0
lo que esperaría que Ruby interpegara como false
y mostrara "Exit Failure" (seguro, entonces la lógica es incorrecta, el ternario necesita ser volteado) - pero la segunda línea debe salir con el estado opuesto, y no lo hace.
Ni siquiera puedo encontrar nada en la documentación sobre cómo hacer esto, y estoy un poco preocupado de que pueda estar haciendo mal?
Basándose en la respuesta de flitzwald - He parcheado mi versión de esto en Net :: SSH (Ruby 1.9+)
class Net::SSH::Connection::Session
class CommandFailed < StandardError
end
class CommandExecutionFailed < StandardError
end
def exec_sc!(command)
stdout_data,stderr_data = "",""
exit_code,exit_signal = nil,nil
self.open_channel do |channel|
channel.exec(command) do |_, success|
raise CommandExecutionFailed, "Command /"#{command}/" was unable to execute" unless success
channel.on_data do |_,data|
stdout_data += data
end
channel.on_extended_data do |_,_,data|
stderr_data += data
end
channel.on_request("exit-status") do |_,data|
exit_code = data.read_long
end
channel.on_request("exit-signal") do |_, data|
exit_signal = data.read_long
end
end
end
self.loop
raise CommandFailed, "Command /"#{command}/" returned exit code #{exit_code}" unless exit_code == 0
{
stdout:stdout_data,
stderr:stderr_data,
exit_code:exit_code,
exit_signal:exit_signal
}
end
end
La siguiente forma de ejecutar procesos con Net :: SSH me parece mucho más útil. Le proporciona stdout
y stderr
distintos, exit code
exit signal
y 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
Espero que esto ayude.