【问题标题】:Fork child process with timeout and capture output具有超时和捕获输出的分叉子进程
【发布时间】:2012-08-24 18:28:38
【问题描述】:

假设我有一个类似下面的函数,我如何捕获 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

谢谢。

【问题讨论】:

    标签: ruby linux windows process stdout


    【解决方案1】:

    您可以使用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:我把超时实现作为作业留给你;-)

    【讨论】:

    • 完美!正是我所追求的,而且比我的解决方案优雅得多:)
    • @TamerShlash 读取Process.wait2 文档,它返回一个元组(两个值),我们将一个分配给status,另一个(第一个)分配给_,这是常见的做法当你想丢弃一个值时。
    【解决方案2】:

    我听从了 Anselm 在 Ruby 论坛 here 上的帖子中的建议。

    函数长这样——

    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。

    【讨论】:

      猜你喜欢
      • 2011-04-04
      • 2023-01-19
      • 2021-02-14
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 2011-11-07
      • 2012-10-04
      • 1970-01-01
      相关资源
      最近更新 更多