sri*_*ger 5 bash shell node.js npm
我正在努力实现节点 API 的正常关闭。通常,在开发过程中,这个过程是使用通用start脚本启动的,但我注意到这会导致一些令人讨厌的行为,令我惊讶的是,在我作为节点开发人员的 3 年左右的时间里,我从未真正注意到过这些行为。
要在开发期间开始关闭,我们只需在 bash 终端中按 ctrl+C,这当然会导致SIGINT将 a 发送到 npm 进程及其所有子进程。我可以使用process.on处理程序捕获此信息,以从那里启动正常关闭 - 关闭新请求,等待现有请求完成,然后终止数据库连接,所有这些好东西。
但是,如果开发人员第二次按下 ctrl+C,npm 的行为会有所不同。它似乎正在向它最初sh用来调用我的脚本的进程发送一个 SIGTERM 。start这会导致该sh进程打印出来Terminated并退出,将终端的控制权返回给用户,而无需等待节点进程退出。
这真的很烦人,因为它给人的印象是节点进程已经停止,但当然它没有。它会一直持续到关闭完成,或者被 SIGKILL 或 SIGQUIT 等强制终止。如果它碰巧将任何内容打印到控制台,它将直接在开发人员现在可能在该终端中运行的任何其他内容中间执行此操作。
对于一个简单的例子,试试这个:
包.json:
{
"private": true,
"scripts": {
"start": "node index.js"
}
}
Run Code Online (Sandbox Code Playgroud)
索引.js:
{
"private": true,
"scripts": {
"start": "node index.js"
}
}
Run Code Online (Sandbox Code Playgroud)
npm start在终端中运行,然后按 ctrl+c 一次。您将看到信号到达节点,但它当然不会退出。现在,再做一次。您将看到信号再次通过,但您会立即看到“Termied”,然后是 shell 提示符。直到你找到节点进程的进程 ID 并杀死它,kill -9你才会继续看到它waiting...您将每隔五秒
我对这个例子做了一些更多的摆弄,看起来 npm 完全对此负责。如果您发送kill -2两次,则会发生 shell 进程的终止,而节点进程不会收到 SIGINT。
所以我有两个主要问题:
这到底是怎么回事?我是否遗漏了有关 shell 工作原理的信息,或者这是 npm run-script 中内置的某种功能?如果是这样,我在哪里可以找到这方面的信息?npm help run-script没有显示任何内容。
我知道start脚本在这样的项目中很常见,所以看起来其他人应该遇到这个问题。人们通常如何处理它?我用谷歌搜索了很多,但很难找到明确的答案。
当然,这不是什么大不了的事。启动脚本只是为了确保在启动之前运行 TS 编译。我可以让开发人员在构建后直接在 shell 中运行构建的应用程序,或者编写一个脚本来执行构建并在 npm 脚本之外启动。但如果不必这样做就好了。
真的,我只是感到困惑,希望得到一些帮助。谢谢!
要回答您的第一眼代码,npm这是预期的处理行为SIGINT。第一次出现的信号会传递给子进程,并附加一次性侦听器SIGINT以立即终止npm父进程。您可以在此处查看代码。
我认为这是因为它npm start仅作为开发阶段的简写,并且在您发现信号处理错误的情况下立即使用“手刹”来终止进程是有意义的(不幸的是,即使这并不在您发现的所有情况下都有效)出去)。
我没有2的答案,但不久前,关于npm信号处理和npm start. 官方 NPM 声明主要是npm start不能替代适当的流程管理器(例如主管或 systemd),并且不应该在这样的生产环境中使用。
编辑: sripberger对2的回答:
我最终做了什么如下。shutdown是一个执行关闭并返回承诺的函数。第一个 SIGINT 将开始关闭,但第二个 SIGINT 将强制终止进程,无论关闭是否完成。这不会阻止 npm 终止 shell 进程,但它确实确保节点进程在发生这种情况时随之终止:
process.once('SIGINT', () => {
console.log('\nShutting down, please wait...');
// Begin the graceful shutdown.
shutdown().catch((err) => {
console.error('Could not shut down gracefully:', err);
});
// Attach a subsequent handler to force kill.
process.on('SIGINT', () => {
console.log('\nProcess killed.');
process.exit(0);
});
});
Run Code Online (Sandbox Code Playgroud)
当然,正如 blami 所指出的,不建议使用 npm 脚本来控制生产中的服务。这只是为了方便开发环境。
| 归档时间: |
|
| 查看次数: |
941 次 |
| 最近记录: |