如何在PM2中实现捕获日志/异常后执行自定义代码再退出进程?
解决PM2环境下Node.js全局异常捕获失效问题
原生Node.js的
uncaughtException监听在PM2环境失效的核心原因是PM2默认会拦截未捕获异常事件,并直接触发进程重启逻辑,业务代码的监听逻辑还没执行完进程就被销毁了,按照以下步骤调整即可正常生效:
步骤1:调整PM2配置
在你的PM2生态配置文件(通常为ecosystem.config.js)中添加以下配置,给业务代码预留足够的异常处理时间:
module.exports = { apps : [{ name: "你的应用名称", script: "你的应用入口文件路径", // 给进程预留5秒的收尾时间,可根据日志写入耗时调整 kill_timeout: 5000, // 如果需要处理完异常后自动重启进程,保留以下配置,不需要自动重启则设为false autorestart: true, // Cluster模式下需要额外添加以下配置,避免主进程拦截异常事件 combine_logs: true, merge_logs: true }] }
配置修改完成后执行pm2 reload ecosystem.config.js生效。
步骤2:调整异常监听代码
注意必须保证日志写入完成后再调用进程退出方法,不要使用异步写日志后直接退出的逻辑:
// 处理同步代码未捕获异常 process.on("uncaughtException", err => { // 优先使用同步方法写入日志,避免异步操作未完成进程就退出 syncWriteErrorLog(err); // 如果必须用异步写日志,要在回调中执行退出 // asyncWriteErrorLog(err, () => { // process.exit(1); // }); process.exit(1); }); // 建议同时补充Promise未捕获异常的监听 process.on("unhandledRejection", (reason, promise) => { const err = new Error(`未捕获的Promise异常,promise:${promise},原因:${reason}`); syncWriteErrorLog(err); process.exit(1); });
注意事项
- 异常监听回调中仅执行日志上报、资源释放这类必要的轻量操作,不要执行复杂业务逻辑,避免触发二次异常
- 如果不需要PM2自动重启进程,将
autorestart配置设为false即可 - 日志写入耗时较长的话可以适当调大
kill_timeout的数值,单位为毫秒
内容的提问来源于stack exchange,提问作者OIRNOIR
相关产品推荐
相关产品推荐

