2011-04-04 78 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