成功执行后,我的 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脚本(逻辑与&&逻辑或||分号;) 成功后执行命令失败后执行命令连续执行命令(无论前者成功与否)

在nodejs的command prompt中执行node进入命令交互模式后怎么退出

脚本退出后执行后台进程

shell的退出状态码