成功执行后,我的 nodejs 脚本不会自行退出
Posted
技术标签:
【中文标题】成功执行后,我的 nodejs 脚本不会自行退出【英文标题】:my nodejs script is not exiting on its own after successful execution 【发布时间】:2014-03-16 21:23:42 【问题描述】:我已经编写了一个脚本来在从 db 表和 solr 读取数据后更新我的 db 表。我正在使用 asyn.waterfall 模块。问题是成功完成所有操作后脚本没有退出。我已经使用了 db 连接池,还认为可能会创建无限等待的脚本。 我想把这个脚本放在 crontab 中,如果它不能正确退出,就会不必要地创建大量实例。
【问题讨论】:
你使用的是什么数据库模块? 我正在使用mysql模块。 如果没有一些代码,这很难调试。你打电话给connection.end()
?
connection.end() 已被弃用,因此不应再使用它。我正在使用连接池和 connection.release()。将代码发布也让我完成..
【参考方案1】:
你必须在完成后通过调用告诉它
process.exit();
更具体地说,您需要在来自 async.waterfall() 的回调中调用它(该函数的第二个参数)。此时,您的所有异步代码都已执行,您的脚本应该可以退出了。
编辑:正如下面@Aaron 所指出的,这可能与数据库连接处于活动状态有关,并且不允许节点进程结束。
【讨论】:
不是因为异步程序,程序setTimeout(function(), 1000)
在1秒后终止就证明了这一点。如果您执行异步操作,Node 绝对足够聪明,可以告诉您何时完成。这个问题更有可能是因为数据库连接(未来事件的可能来源)保持打开状态。
process.exit() 似乎是最明显的事情。但是为什么需要显式调用它呢?脚本应该自行退出
可能是我做事的方式不对,我想我已经弄清楚了。将在同一更新让我现在修复它.....
@AaronDufour 是对的,这就像您创建 redis
节点客户端并且最后没有断开连接一样。
我赞成“编辑”关于数据库连接处于活动状态,而不是 process.exit() 部分。我没有意识到我必须手动关闭与 mongoDB 的连接才能结束我的节点进程。现在它按预期自行关闭。【参考方案2】:
我刚刚经历了这个问题。
仅使用process.exit()
的问题在于我正在处理的程序正在创建句柄,但从未销毁它们。
它正在处理一个目录并将数据放入orientdb。
所以我学到的一些东西是在摆脱引用之前需要关闭数据库连接。而process.exit()
并不能解决所有情况。
当我的项目处理 2,000 个文件时。它会减少到大约 500 个,并且额外的句柄会填满可用的工作内存。这意味着它将无法继续。因此永远不会到达最后的process.exit
。
另一方面,如果您关闭请求应用保持打开状态的项目,则可以从源头解决问题。
我能够使用的两个“未记录的函数”是
process._getActiveHandles();
process._getActiveRequests();
我不确定还有哪些其他功能可以帮助调试这些类型的问题,但这些功能非常棒。
它们返回一个数组,您可以通过使用这些方法来确定您的流程中发生的很多事情。
我只是希望能帮助其他偶然发现这篇文章的人。
【讨论】:
谢谢,这正是我解决这个问题所需要的。像调用process.exit();
这样的解决方案是围绕您有某种活动的事件侦听器、超时等这一事实进行的黑客攻击......这些函数允许您实际跟踪它们并编写适当的清理代码!
我建议使用像 wtfnode、why-is-node-running 或 active-handles 这样的 NPM 模块来确定是哪段代码导致了问题。
在 TS 4.4.2 中不起作用。还是我做错了什么?
@KonradGałęzowski 它们是无证的,你会得到 TypeScript 错误,但这些错误只是因为 TypeScript 不知道它们在那里。他们工作得很好。如果您想消除 TypeScript 错误,您必须使用这些函数来扩充 Node.js 模块,但如果您只是要使用它们进行调试,则没有必要,只是不要输入错误。【参考方案3】:
我们可以使用以下命令退出执行:
connection.destroy();
【讨论】:
【参考方案4】:可以使用节点模块why-is-node-running:
运行npm install -D why-is-node-running
在您的代码中添加import * as log from 'why-is-node-running';
当你希望你的程序退出时,添加一条日志语句:
afterAll(async () =>
await app.close();
log();
)
这将打印一个带有堆栈跟踪的打开句柄列表,以找出它们的来源:
There are 5 handle(s) keeping the process running
# Timeout
/home/maf/dev/node_modules/why-is-node-running/example.js:6 - setInterval(function () , 1000)
/home/maf/dev/node_modules/why-is-node-running/example.js:10 - createServer()
# TCPSERVERWRAP
/home/maf/dev/node_modules/why-is-node-running/example.js:7 - server.listen(0)
/home/maf/dev/node_modules/why-is-node-running/example.js:10 - createServer()
【讨论】:
超级好用的模块!我必须将它导入为import log from 'why-is-node-running'
和node --experimental-modules
,但它是did the job!
也可以单独运行Why-is-node-running(参见文档)
第一个代码sn-p的末尾是不是应该多加)
?
如果您通过node file.js
调用脚本,它更易于使用:why-is-node-running file.js
就像一个调试器工具,而不是在应用程序本身中需要它。
即使在今天也发现这很有帮助。只是也有调用的 CLI 方法。【参考方案5】:
如果您使用 Visual Studio 代码,则可以直接从它附加到已运行的 Node 脚本。
首先,运行 Debug: Attached to Node Process 命令:
当您调用该命令时,VS Code 会提示您附加到哪个 Node.js 进程:
您的终端应显示此消息:
Debugger listening on ws://127.0.0.1:9229/<...>
For help, see: https://nodejs.org/en/docs/inspector
Debugger attached.
然后,在您的调试控制台中,您可以使用来自The Lazy Coder’s answer 的代码:
process._getActiveHandles();
process._getActiveRequests();
【讨论】:
发现这很有帮助。谢谢以上是关于成功执行后,我的 nodejs 脚本不会自行退出的主要内容,如果未能解决你的问题,请参考以下文章
shell 判断脚本执行是否成功 if [ $? -ne 0 ]
在 Node.js 中如何停止脚本执行,成功向控制台写入错误消息,然后退出脚本?
shell脚本(逻辑与&&逻辑或||分号;) 成功后执行命令失败后执行命令连续执行命令(无论前者成功与否)