假设我有类似下面的函数,如何捕获Process.spawn调用的输出?如果进程花费的时间超过指定的超时时间,我也应该能够终止进程。
请注意,该功能还必须是跨平台的(Windows / Linux)。
def execute_with_timeout!(command)
begin
pid = Process.spawn(command) # How do I capture output of this process?
status = Timeout::timeout(5) {
Process.wait(pid)
}
rescue Timeout::Error
Process.kill('KILL', pid)
end
end
感谢。
答案 0 :(得分:12)
您可以使用IO.pipe
并告诉Process.spawn
使用重定向输出而无需外部gem。
当然,只从Ruby 1.9.2开始(我个人推荐1.9.3)
以下是Spinach BDD内部用于捕获out和err输出的简单实现:
# stdout, stderr pipes
rout, wout = IO.pipe
rerr, werr = IO.pipe
pid = Process.spawn(command, :out => wout, :err => werr)
_, status = Process.wait2(pid)
# close write ends so we could read them
wout.close
werr.close
@stdout = rout.readlines.join("\n")
@stderr = rerr.readlines.join("\n")
# dispose the read ends of the pipes
rout.close
rerr.close
@last_exit_status = status.exitstatus
原始来源位于features/support/filesystem.rb
强烈建议您阅读Ruby自己的Process.spawn文档。
希望这有帮助。
PS:我把超时实现作为你的作业; - )
答案 1 :(得分:3)
我在Ruby论坛here的帖子中关注了Anselm的建议。
该功能如下所示 -
def execute_with_timeout!(command)
begin
pipe = IO.popen(command, 'r')
rescue Exception => e
raise "Execution of command #{command} unsuccessful"
end
output = ""
begin
status = Timeout::timeout(timeout) {
Process.waitpid2(pipe.pid)
output = pipe.gets(nil)
}
rescue Timeout::Error
Process.kill('KILL', pipe.pid)
end
pipe.close
output
end
这可以完成这项工作,但我宁愿使用包含此功能的第三方gem。有人有更好的方法吗?我已经尝试了Terminator,它完全符合我的要求,但它似乎无法在Windows上运行。