2011-04-04 80 views
7

我將有一個用於處理Web服務器重啓的父進程。它會發信號通知孩子停止收聽新的請求,孩子會通知父母它已經停止收聽,然後家長會發信號通知新孩子它可以開始收聽。通過這種方式,我們可以實現小於100ms的停機時間,以便重新啓動該級別(我也有一個零停機時間的重啓,但這並不總是足以重啓)。父進程退出時檢測

服務管理器將在關閉時關閉父項。孩子如何檢測父母已經結束?

信號使用子進程的標準輸入和標準輸出發送。也許我可以檢測stdin流的結束?我希望避免輪詢間隔。另外,如果可能的話,我希望這是一個非常快速的檢測。

回答

5

您可以在父進程中添加一個exit listener來發信號通知孩子嗎?

編輯:
您還可以使用node-ffi (Node Foreign Function Interface)打電話...
prctl(PR_SET_PDEATHSIG, SIGHUP);
...在Linux中。 (man 2 prctl

+0

「斷開」註冊我認爲這會工作。在關閉時,父母被殺,但我確信退出偵聽器仍然可以工作。也許我仍然可以[每隔幾秒檢查一次父進程ID](http://stackoverflow.com/questions/5566009/node-js-parent-process-id),如果它變成了數字1,那就意味着父代已經死了。 – 2011-04-06 12:03:58

+3

如果您正在關閉,您的進程將首先收到「SIGTERM」。你可以捕獲這個,並以這種方式進行清理: 'process.on('SIGTERM',function(){ console.log('SIGTERM,exiting ...'); //在這裏做一些清理。 ... process.exit(0); });' – entropo 2011-04-06 17:07:44

+0

是的,讓孩子定期檢查他們的'PPID'是否變成'1',這對父母沒有乾淨地離開的情況來說是一個很好的回退。另請參閱:http:// stackoverflow。com/questions/269494/how-can-i-cause-a-child-process-exit-when-the-parent-does – entropo 2011-04-06 17:25:11

6

此答案只是用於提供entropo節點-FFI溶液的一個例子提出了(見上文)(如所提到的,將在Linux上工作):

這是父進程,它是產卵子,然後退出5秒後:

var spawn = require('child_process').spawn; 
var node = spawn('node', [__dirname + '/child.js']); 
setTimeout(function(){process.exit(0)}, 5000); 

這是子進程(位於child.js)

var FFI = require('node-ffi'); 
var current = new FFI.Library(null, {"prctl": ["int32", ["int32", "uint32"]]}) 

//1: PR_SET_PDEATHSIG, 15: SIGTERM 
var returned = current.prctl(1,15); 

process.on('SIGTERM',function(){ 
     //do something interesting 
     process.exit(1); 
}); 

doNotExit = function(){ 
     return true; 
}; 
setInterval(doNotExit, 500); 

而不current.prctl(1,15)即使父母死亡,孩子也會永遠跑步。這裏將會用SIGTERM發出信號,這將被優雅地處理。

+0

對於那些實施此解決方案的人。在你實際完成之前,不要調用process.exit(1)。 logger.warn(「SIGTERM。正在退出」,function(){process.exit(1);}) – itaifrenkel 2014-07-16 09:45:39

2

我從本機OSX應用程序中啓動Node.JS作爲後臺工作。爲了使Node.js的退出時消耗node.js的標準輸出父進程死亡/退出,我做了以下內容:

// Watch parent exit when it dies 

process.stdout.resume(); 
process.stdout.on('end', function() { 
 process.exit(); 
}); 

容易這樣,但我不能完全肯定,如果這是你經歷了什麼要求;-)

+0

我一直在爲這個用例而苦苦掙扎,而且這個工作非常出色。乾杯! – sak 2017-10-21 12:40:58

13

一個簡單的解決方案可能是通過在子進程

process.on('disconnect', function() { 
    console.log('parent exited') 
    process.exit(); 
}); 
+0

謝謝!我試了一切,這似乎是唯一的方式來捕捉你的父進程被殺死-9。 – 2014-05-17 21:26:03

+0

我完全同意這是很好的解決方案。在我的情況下,我正在偵聽來自父進程的SIGTERM事件,並且在斷開連接事件時(如果有什麼不好的事情發生,我需要重啓父進程)。在我的情況下,問題是顯而易見的,因爲子進程創建服務器端口,所以再次啓動會導致「ERRADDRINUSE」。這解決了問題:) – JakubKnejzlik 2014-12-23 02:39:18