【问题标题】:Detect when parent process exits检测父进程何时退出
【发布时间】:2011-07-29 07:36:17
【问题描述】:

我将有一个用于处理网络服务器重启的父进程。它会向孩子发出停止监听新请求的信号,孩子会向父母发出停止监听的信号,然后父母会向新的孩子发出可以开始监听的信号。通过这种方式,我们可以完成不到 100 毫秒的停机时间来重新启动该级别(我也有一个零停机时间的孙子重新启动,但这并不总是足够的重新启动)。

服务管理器将在关闭时终止父级。子如何检测到父已结束?

使用子进程的标准输入和标准输出发送信号。也许我可以检测到标准输入流的结束?我希望避免轮询间隔。另外,如果可能的话,我希望这是一个非常快速的检测。

【问题讨论】:

    标签: node.js process watchdog


    【解决方案1】:

    您可以在父进程中添加一个exit listener 来向子进程发出信号吗?

    编辑:
    您也可以使用node-ffi (Node Foreign Function Interface)拨打...
    prctl(PR_SET_PDEATHSIG, SIGHUP);
    ...在 Linux 中。 (man 2 prctl)

    【讨论】:

    • 我认为这会奏效。当需要关闭时,父母会被杀死,但我很确定退出侦听器仍然可以工作。也许我仍然可以check for a parent process id every few seconds,如果它变成数字 1,那就意味着父母已经死了。
    • 如果您要关闭,您的进程将首先收到SIGTERM。您也可以通过这种方式捕获并进行清理:process.on('SIGTERM', function () { console.log('Got SIGTERM, exiting...'); // do some cleanup here... process.exit(0); });
    • 是的,让孩子定期检查他们的PPID 是否变为1 对于父母没有干净退出的情况是一个很好的后备方案。另见:stackoverflow.com/questions/269494/…
    【解决方案2】:

    此答案仅用于提供 entropo 提出的 node-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 发出信号,这将被优雅地处理。

    【讨论】:

    • 对于那些实施此解决方案的人。在实际完成之前不要调用 process.exit(1)。 logger.warn("SIGTERM。优雅退出。", function() {process.exit(1);})
    • 看起来 node-ffi 已被弃用,取而代之的是较新的模块“ffi”。
    【解决方案3】:

    我从本地 OSX 应用程序中作为后台工作程序启动 Node.JS。为了让 node.js 在消耗 node.js stdout 的父进程死亡/退出时退出,我执行以下操作:

    // Watch parent exit when it dies
    
    process.stdout.resume();
    process.stdout.on('end', function() {
      process.exit();
    });
    

    就这么简单,但我不确定这是否是您一直要求的 ;-)

    【讨论】:

    • 我在这个用例上苦苦挣扎,而且效果很好。干杯!
    • process.stdout.resume() 我崩溃了。
    • 似乎这是一个古老的用法。删除resume() 开始工作。另外,原来我正在寻找的事件是error
    【解决方案4】:

    更简单的解决方案是在子进程中注册“断开连接”

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

    【讨论】:

    • 谢谢!我尝试了所有方法,这似乎是捕获您的父进程已被杀死 -9 的唯一方法。
    • 我完全同意这是一个很好的解决方案。在我的情况下,我正在监听来自父进程的 SIGTERM 事件以及(如果发生任何不好的事情并且我需要重新启动父进程)断开事件。在我的情况下,问题很明显,因为子进程创建了服务器持有端口,所以再次启动会导致“ERRADDRINUSE”。这解决了问题:)
    猜你喜欢
    • 1970-01-01
    • 2010-09-21
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多