【问题标题】:Node.js getting SIGINT from pm2Node.js 从 pm2 获取 SIGINT
【发布时间】:2018-11-09 11:03:54
【问题描述】:

我正在尝试使用 pm2 将我的节点应用程序作为服务运行。

现在,启动和停止应用程序正常工作。但是,我想做一个优雅的关机。

我的应用程序已经监听 SIGINT,关闭服务器然后退出进程。然而,试图让 pm2 发送 SIGINT,只会导致应用程序重新启动,就像 pm2 正在杀死并重新启动它一样。

这就是我创建流程的方式:

pm2 start server.js --name ProcessName --silent --kill-timeout 3000

这是我的应用程序监听 SIGINT 的代码:

process.on("SIGINT", function () {
    //graceful shutdown
    server.end().then(() => {
        process.exit();
    }).catch((err) => {
        console.error(err);
    });

});

然后使用 pm2 关闭应用程序,我正在运行:

pm2 sendSignal SIGINT ProcessName

这又会重新启动应用程序。

阅读 pm2 文档,我发现 pm2 也会向应用发送shutdown 事件,所以我补充说:

process.on('message', function(msg) {
    if (msg == 'shutdown') {
        server.end().then(() => {
            process.exit();
        }).catch((err) => {
            console.error(err);
        });
    }
});

这也不起作用。

知道如何解决这个问题吗?

谢谢!

【问题讨论】:

  • 正常启动你的代码不会崩溃吗? (喜欢node server.js
  • 不,它工作得很好。当我按下 CTRL+C 并优雅地存在(在日志文件和所有内容中记录一些输出)时,它确实捕获了 SIGINT。
  • 啊,我误解了这个问题。改为使用pm2 stop 关闭应用程序。这会发送 sigint 并且不会重新启动它。
  • @ReverseCold 已经尝试过了。停止命令发送一个 SIGINT 但应用程序永远不会得到它,它确实停止了应用程序,但不是优雅的。运行 pm2 monit 您会看到发送了 SIGINT。我在想发生了一些奇怪的事情,也许 pm2 包装进程被 SIGINT 而不是应用程序本身杀死了。我不知道...试图找到一个解释。
  • 是否以常规方式启动应用程序并发送信号?

标签: node.js pm2


【解决方案1】:

如果你还没有解决它...

根据您提供的信息,我假设您在 Windows 上运行它。

您的应用无法在 Windows 上捕获 PM2 发送的 SIGINT
shutdown 消息也适用于 Windows,但它只能由 gracefulReload 命令发送。


(更新)
这些不是完整的解决方案,但可能会有所帮助(希望......)

sendSignal 命令最终会调用process.kill(),其中一些signals 可能会起作用(尚未尝试过)。

我还找到了以下方法。这可以在不重新启动的情况下正常关闭进程仅当 autorestart 选项打开关闭
然后你的集群不会在发生事故时重新加载,所以它可能不是你想要的......

pm2 可让您发送自定义消息 (reference)。
将下面的代码放在一个新文件中:

var pm2 = require('pm2');
var id = process.argv[2];

pm2.connect(() => {
  pm2.sendDataToProcessId({
    type: 'shutdown',
    data:{some: 'data'},
    id: id,
    topic: 'some topic'
  }, (err, res) => {
    console.log('message sent');
    pm2.disconnect();

    if(err) throw err;
  })
});

修改监听shutdown消息的部分如下:

process.on('message', function(msg){
  if(msg == 'shutdown' || msg.type == 'shutdown'){
    // code to clean up
  }
});

然后运行带有node 的第一个文件,并以您要关闭的集群的id 作为参数。

条件中额外msg.type == 'shutdown' 的原因是pm2.sendDataToProcessId() 要求参数是具有这些键的对象,并且不接受简单的shutdown 字符串。

【讨论】:

  • 但是gracefulReload会在关机后重新加载应用,对吧?
  • 是的,确实如此。没有?
  • 就是这样。我不想重新启动它。我想优雅地关闭它。
  • @FedeE。您最终是否设法解决了这个问题?我面临着同样的事情。我可以使用自定义消息路由,但想知道您是否发现了更干净的东西?
  • @Ian 不。我无法找到解决方案。
【解决方案2】:

通常pm2 stop 是停止您的应用程序的正确方法。但是,如果您在 Docker 内部运行应用程序,则需要使用 pm2-runtime 而不是 pm2,它是 pm2 npm 包的一部分,并将系统 SIGINT 传递给所有子进程。见http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs

【讨论】:

    【解决方案3】:

    在您的第一个示例中应该可以捕获信号并优雅地退出。

    要真正停止服务器,请使用pm2 stop 而不是pm2 sendSignal SIGINT ProcessName

    http://pm2.keymetrics.io/docs/usage/signals-clean-restart/

    【讨论】:

      猜你喜欢
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2021-03-28
      • 1970-01-01
      • 2015-04-15
      • 1970-01-01
      相关资源
      最近更新 更多