我正在尝试使用 pm2 将我的节点应用程序作为服务运行。
现在,可以启动和停止应用程序。但是,我想要优雅地关闭。
我的应用程序已经侦听 SIGINT,关闭服务器,然后退出进程。然而,尝试让 pm2 发送 SIGINT,只会导致应用程序重新启动,就像 pm2 杀死并再次启动它一样。
这就是我创建流程的方式:
pm2 启动 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 进程名称
再次重新启动应用程序。
阅读 pm2 文档,我发现 pm2 还会向应用程序发送
shutdown
事件,所以我添加了:
process.on('message', function(msg) {
if (msg == 'shutdown') {
server.end().then(() => {
process.exit();
}).catch((err) => {
console.error(err);
});
}
});
这也不起作用。
知道如何解决这个问题吗?
谢谢!
如果你还没有解决...
根据您提供的信息,我假设您在 Windows 上运行它。
您的应用无法捕获 Windows 上 PM2 发送的
SIGINT
。shutdown
消息也适用于 Windows,但只能通过 gracefulReload
命令发送。
(更新)
这些不是完整的解决方案,但可能会有所帮助(希望......)
sendSignal
命令最终调用 process.kill()
,其中一些 信号 可能会起作用(尚未尝试)。
我还发现了以下方法。仅当 autorestart
选项打开off时,这才可以正常关闭进程而无需重新启动。
pm2 可让您发送自定义消息(参考)。
将以下代码放入新文件中:
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
字符串。
一般来说,
pm2 stop
是停止应用程序的正确方法。但是,如果您在 Docker 内部运行应用程序,则需要使用 pm2-runtime
而不是 pm2
,它是 pm2
npm 包的一部分,并将系统 SIGINT
传递给所有子进程。请参阅 http://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs
捕获信号并优雅退出应该可以在您的第一个示例中起作用。
要实际停止服务器,请使用
pm2 stop
而不是 pm2 sendSignal SIGINT ProcessName
。
参见 http://pm2.keymetrics.io/docs/usage/signals-clean-restart/
对于 Windows 服务器,您可能还需要捕获
SIGBREAK
。请务必尝试使用该方法以及 SIGINT
和 SIGTERM
来正常关闭。
使用 pm2 start app.js —shutdown-with-message 运行应用程序
使用 pm2 stop app.js 停止应用程序