【发布时间】:2022-11-11 07:30:33
【问题描述】:
我有一个node.js 脚本可以在控制台中正常运行和退出,但除非我在pm2 中调用process.exit(),否则它不会退出。 PM2 配置为:
{
name: "worker",
script: "./worker.js",
restart_delay: 60000,
out_file: "/tmp/worker.log",
error_file: "/tmp/worker_err.log"
},
我已经安装了why-is-node-running,以查看是什么让进程在预期退出后 10 秒内保持运行,输出为:
There are 9 handle(s) keeping the process running
# TLSWRAP
node:internal/async_hooks:200
# TLSWRAP
node:internal/async_hooks:200
# ZLIB
node:internal/async_hooks:200
/Users/r/code/app/node_modules/decompress-response/index.js:43 - const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:586
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:768
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:786
# TLSWRAP
node:internal/async_hooks:200
# ZLIB
node:internal/async_hooks:200
/Users/r/code/app/node_modules/decompress-response/index.js:43 - const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:586
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:768
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:786
# TLSWRAP
node:internal/async_hooks:200
# ZLIB
node:internal/async_hooks:200
/Users/r/code/app/node_modules/decompress-response/index.js:43 - const decompressStream = isBrotli ? zlib.createBrotliDecompress() : zlib.createUnzip();
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:586
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:768
file:///Users/r/code/app/node_modules/got/dist/source/core/index.js:786
# TLSWRAP
node:internal/async_hooks:200
# Timeout
node:internal/async_hooks:200
node:internal/async_hooks:468
node:internal/timers:162
node:internal/timers:196
file:///Users/r/code/app/worker.js:65
node:internal/process/task_queues:94
为什么节点不退出?我该如何进一步调试呢?
PS:抱歉贴大了
更新
我设法在一个可笑的小 2 班轮中重现了这一点:
import got from "got";
await got.post('https://anty-api.com/browser_profiles', {form: {a: 123}}).json();
上面的代码在运行窗体控制台时按预期抛出,但在被pm2 调用时会一直运行。
更新 2
它也确实使用空的应用程序文件进行复制。
【问题讨论】:
-
你在这里有很多细节,但一个重要的步骤是将重现问题所需的代码量减少到可以在此处发布的内容。有趣的是,它在 ZLIB TLSWRAP 和超时的上下文中提到了
got模块。但是我们没有实际的代码来查看发生了什么。你能把它减少到几行重现问题并发布一些代码吗? -
我的第一个想法是:pm2 是否使用与从控制台启动它时相同的权限、参数、环境变量和工作目录来启动您的进程?可能是失败的文件/网络操作,然后忽略解决某些问题。
-
@Wyck,谢谢,我做到了。请检查我的更新
-
当我尝试这个时,我得到一个 HTTP 401 Unauthorized 响应,
got将其作为异常抛出。您可笑的小复制品无法处理此异常。 pm2 可以区分崩溃(由于未处理的异常)和干净退出之间的区别。这可能是怎么回事?比较:got.post('https://anty-api.com/browser_profiles', {form: {a: 123}}).json().catch(console.error);(或在您等待的方法中尝试/捕获。) -
等一下……这会用空的 app.js 文件重现吗?您是否可能只是误解了在 pm2 的上下文中“退出”的含义?你了解ProcessContainerFork.js 的作用吗?节点过程当您的模块返回时,不会在 fork 模式下停止,因为它保持与上帝进程的连接。 (这也是您在手动添加
application.exit()时观察到重新启动的原因。)如果这使用空的 app.js 重现,那么您应该修改您的问题。
标签: node.js pm2 node.js-got