【问题标题】:How to timeout subprocess in Ruby如何在Ruby中超时子进程
【发布时间】:2012-06-09 19:35:24
【问题描述】:

我想测试一个进程是否正在运行,所以我运行:

cmd = "my unix command"
results = `#{cmd}`

如何为命令添加超时,以便在超过 x 秒的情况下我可以假设它不起作用?

【问题讨论】:

    标签: ruby timeout


    【解决方案1】:

    Ruby 附带 Timeout module

    require 'timeout'
    res = ""
    status = Timeout::timeout(5) {res = `#{cmd}`} rescue Timeout::Error
    
    # a bit of experimenting:
    
    res = nil
    status = Timeout::timeout(1) {res = `sleep 2`} rescue Timeout::Error 
    p res    # nil
    p status # Timeout::Error
    
    res = nil
    status = Timeout::timeout(3) {res = `sleep 2`} rescue Timeout::Error 
    p res    # ""
    p status # ""
    

    【讨论】:

    • 如果遇到超时需要做点什么,一定要抢救Timeout::Error
    • 是的。我应该提到它。
    • 如果你在超时块内启动它,请确保你杀死 shell 进程。因为它一直在运行。见stackoverflow.com/questions/8292031/…
    【解决方案2】:

    把它放在一个线程中,让另一个线程休眠 x 秒,如果它还没有完成,则杀死第一个线程。

    process_thread = Thread.new do
      `sleep 6` # the command you want to run
    end
    
    timeout_thread = Thread.new do
      sleep 4   # the timeout
      if process_thread.alive?
        process_thread.kill
        $stderr.puts "Timeout"
      end
    end
    
    process_thread.join
    timeout_thread.kill
    

    steenslag 的更好 :) 这是低科技路线。

    【讨论】:

      【解决方案3】:

      使用线程更简单的方法:

      p = Thread.new{ 
         #exec here
      }
      if p.join( period_in_seconds ).nil? then
         #here thread p is still working
         p.kill
      else
         #here thread p completed before 'period_in_seconds' 
      end
      

      【讨论】:

        【解决方案4】:

        对前面答案的一个警告,如果子进程使用sudo,那么你不能杀死子进程,你会创建僵尸进程。

        您需要定期运行Process::waitpid(-1, Process::WNOHANG) 来收集子进程的退出状态并清理进程表(从而清理僵尸进程)。

        【讨论】:

          猜你喜欢
          • 2011-11-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-13
          • 2011-04-22
          相关资源
          最近更新 更多