8

我在运行的一个 Nodejs 应用程序上遇到了一个问题npm start(它就是这样node app.js)。

我的应用程序包含一个信号处理程序,如下所示:

process.on('SIGINT', () => {
    db.disconnect().then({
        process.exit(0);
    }).catch(e => process.exit(1));
});

有相应的日志。在对其他文件进行一些测试之后,我注意到npm如果第一个文件退出时间太长,则在进程上按 Ctrl-C 会触发两次 SIGINT。(尝试在示例应用程序上添加超时)。

现在我已经添加了一个计数器来检查调用是否被多次执行,但我不确定这是关于这个问题的“要走的路”。我猜测 npm 进程上的 SIGINT 预计会在某个时间范围内退出,这就是 npm 再传递一次(总是只有两次)的原因。

有没有人遇到过这个问题并找到了可行的解决方案?

谢谢!

4

3 回答 3

3

我知道这篇文章已经存在了一段时间,但不幸的是我遇到了同样的问题。运行时只node <app.js>触发一个信号。如果运行,该信号会出现两次npm start。取而代之的是计数器,我建议检查服务器是否仍在侦听,如果是,请继续执行您的逻辑和内部终止(例如数据库连接等):

process.on('SIGINT', function(){
 if (server.listening) {
    server.close(function (err) {
      if (err) {
        console.error(err);
        process.exit(1)
      }
      process.exit(0);
    })
 }
})
于 2020-01-27T14:35:03.020 回答
2

您可能希望直接通过 node 运行命令,而不是通过npm start. NPM 可能会导致奇怪的信号捕获,请参阅https://lisk.io/blog/tutorial/why-we-stopped-using-npm-start-child-processes

您的 SIGINT 处理程序可能会被多次调用,您应该编写代码来防止这种情况发生。

此外,如果您正在运行父/子进程,请参阅https://github.com/jtlapp/node-cleanup

当您按下 Ctrl-C 时,您会向当前进程组中的每个进程发送一个 SIGINT 信号。进程组是一组进程,它们都应该作为一个组一起结束,而不是独立地持续存在。但是,某些程序(例如 Emacs)会拦截并重新使用 SIGINT,以便它不会结束进程。在这种情况下,SIGINT 不应结束该组的任何进程。

此外,大多数时候不需要调用 process.exit,请参阅https://nodejs.org/api/process.html#process_process_exit_code

取而代之的是 set process.exitCode,删除您的信号处理程序,然后通过重新发出信号process.kill(process.pid, signal)

于 2020-02-18T04:56:02.637 回答
0

一个更简洁的解决方案是将断开连接的处理程序包装在 promise 中,并且由于 promise 内部实现,resolve 只会被调用一次。

new Promise((resolve) => process.on('SIGINT', resolve))
   .then(() => db.disconnect())
   .then(() => process.exit(0))
   .catch(() => process.exit(1));

注意:我建议避免显式调用 process.exit() 并让节点自行退出。如果由于某些原因进程没有退出,则意味着有一些东西阻止了它(例如:端口监听、打开/挂起的 tcp 连接、未清除setIntervalsetTimeout引用)

于 2021-02-02T10:52:21.830 回答