【问题标题】:Ruby daemon with clean shutdown干净关闭的 Ruby 守护进程
【发布时间】:2011-08-13 04:57:57
【问题描述】:

我想制作一个 ruby​​ 守护程序,它可以使用 kill 命令优雅地关闭。 我想添加一个信号陷阱,它会等到#code that could take some time to run 完成后再关闭。我如何将其添加到这样的内容中:

pid = fork do
   pid_file = "/tmp/pids/daemon6.pid"
   File.open(pid, 'w'){ |f| f.write(Process.pid) }
   loop do
      begin
         #code that could take some time to run
      rescue Exception => e
         Notifier.deliver_daemon_rescued_notification(e)
      end
      sleep(10)
   end
end
Process.detach pid

另外,将它放在单独的脚本中会更好吗,例如单独的 kill 脚本,而不是将其作为守护程序代码的一部分?就像monitGod 会打电话阻止它?

感谢任何建议。

【问题讨论】:

    标签: ruby daemon


    【解决方案1】:

    你可以抓到Interrupt,像这样:

    pid = fork do
      begin
        loop do
          # do your thing
          sleep(10)
        end
      rescue Interrupt => e
        # clean up
      end
    end
    Process.detach(pid)
    

    您可以对Signal.trap('INT') { ... } 执行相同的操作,但在涉及sleep 时,我认为捕获异常更容易。

    更新:这是一种更传统的方法,它确保循环总是在停止之前完成一个完整的循环:

    pid = fork do
      stop = false
      Signal.trap('INT') { stop = true }
      until stop
        # do your thing
        sleep(10)
      end
    end
    

    缺点是它总是会执行sleep,所以几乎总是会有延迟,直到你杀死它后进程停止。您可能可以通过突发睡眠或组合变体来解决这个问题(在sleep 周围拯救Interrupt 或其他东西)。

    【讨论】:

    • 感谢您的回复theo,问题是捕获中断不会让主循环完成。我想做的是捕捉中断,让循环在它开始时完成,然后清理并终止进程。
    • 我已经用另一种更优雅的退出方式更新了我的答案(但sleep 有问题)。
    • 那会很好。谢谢!如果从 until 循环中取出 sleep 调用会怎样?我认为 ruby​​ 的睡眠已经爆发,因此 INT 信号应该将其从睡眠中踢出来。无论如何,额外的睡眠是一个比在循环中间停止进程要小得多的问题。
    • 用 if !stop 保护睡眠,所以如果它在你工作时出现中断,它根本不会进入睡眠状态并立即停止循环。剩下的就是在睡眠中打断 - 我不知道它是否会突然进入睡眠状态。
    猜你喜欢
    • 2014-09-01
    • 1970-01-01
    • 2012-10-03
    • 2011-01-30
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    相关资源
    最近更新 更多