2011-04-26 132 views
7

我想製作一個ruby守護進程,它會正常關閉kill命令。 我想添加一個信號陷阱,等到#code that could take some time to run完成後關閉。我怎麼想補充一點,以這樣的:乾淨關機的Ruby守護進程

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 

而且,會是更好的有,在一個單獨的腳本,就像一個單獨的殺腳本,而不是具有其作爲守護進程代碼的一部分?像monit或會調用來阻止它?

我欣賞任何建議。

回答

7

你能趕上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 ,所以幾乎總是會有一個延遲,直到你殺死它之後該進程停止。你也許可以通過睡覺或者組合變體來解決這個問題(拯救Interrupt,就在sleep附近)。

+0

感謝您的回覆theo,問題是捕獲中斷不會讓主循環結束。我想要做的是捕捉中斷,讓循環完成,如果它開始,然後清理並殺死進程。 – fflyer05 2011-04-26 18:10:21

+0

我已經用另一種更優雅的方式更新了我的答案(但是卻有'sleep'問題)。 – Theo 2011-04-26 20:24:50

+0

這樣做會很好。謝謝!如果睡眠呼叫被從直到循環中取出,該怎麼辦?我認爲紅寶石的睡眠已經爆發了,所以INT信號應該把它從睡眠中解放出來。無論如何,額外的睡眠是一個更小的問題,然後停止在循環中的過程。 – fflyer05 2011-04-26 21:22:25