如何使用 Ruby 的 Net::SSH 库获取退出状态?
我有一段代码,只是尝试在远程服务器上执行脚本,如果失败,我想进行后续调用,想象一下:
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
我希望(忽略 stdout 和 stderr在我设计的示例中打印) - 但第一行应该以 0
退出,我希望 Ruby 会解释为 false
并显示“退出失败”(当然,所以逻辑是错误,三元需要翻转) - 但第二行应该以相反的状态退出,但事实并非如此。
我什至在文档中找不到有关如何执行此操作的任何内容,我有点担心我可能做错了?!
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?!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(3)
基于 flitzwald 的答案 - 我已经将我的版本修补到 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
对于较新版本的 Net::SSH,您只需将状态哈希传递给 Net::SSH::Connection::Session#exec:
status = {}
Net::SSH.start(hostname, user, options) do |ssh|
channel = ssh.exec(command, status: status)
channel.wait # wait for the command to actually be executed
end
puts status.inspect
# {:exit_code=>0}
默认情况下,exec
会传输其输出到 $stdout
和 $stderr
。您可以将一个块传递给 exec 来执行不同的操作,例如:
ssh.exec(command, status: status) do |ch, stream, data|
if stream == :stdout
do_something_with_stdout(data)
else
do_something_with_stderr(data)
end
end
这适用于 6.1.0 - 不确定旧版本的可用性。请参阅 http://net -ssh.github.io/net-ssh/Net/SSH/Connection/Session.html#method-i-exec 了解更多详细信息。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我发现以下使用 Net::SSH 运行进程的方法更有用。它为您提供了不同的
stdout
和stderr
、退出代码
和退出信号
。希望这有帮助。
I find the following way of running processes with Net::SSH much more useful. It provides you with distinct
stdout
andstderr
,exit code
andexit signal
.Hope this helps.