详解主动终止Node.js进程的几种方法
本篇文章给大家介绍一下主动触发Node进程终止的一些方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
有几个原因会导致 Node.js 进程终止。其中一些是可以避免的,例如抛出错误时,而另一些是无法防止的,例如内存不足。全局 process
是一个 Event Emitter 实例,当执行正常退出时,将发出一个 exit
事件。然后程序代码可以通过侦听这个事件来执行最后的同步清理工作。
相关推荐:《nodejs 教程》
下面是可以主动触发进程终止的一些方法:
操作 | 例子 |
---|---|
手动流程退出 | process.exit(1) |
未捕获的异常 | throw new Error() |
未兑现的 promise | Promise.reject() |
忽略的错误事件 | EventEmitter#emit('error') |
未处理的信号 | $ kill <PROCESS_ID> |
其中有许多是属于偶然被触发的,例如未捕获的错误或未处理的 promise,但是其中也有为了直接使进程终止而创建的。
进程退出
使用 process.exit(code)
来终止进程是最直接的方法。这在当你知道自己的过程已经到了生命周期的尽头时非常有用。 code
值是可选的,默认值为0,最大可以设为 255。0 表示进程运行成功,而任何非零的数字都表示发生了问题。这些值可以被许多不同的外部工具使用。例如当测试套件运行时,非零值表示测试失败。
直接调用 process.exit()
时,不会向控制台写入任何隐式文本。如果你编写了以错误表示形式调用此方法的代码,则你的代码应该用户输出错误来帮助他们解决问题。例如运行以下代码:
$ node -e "process.exit(42)" $ echo $?
在这种情况下,单行的 Node.js 程序不会输出任何信息,尽管 shell 程序确实会打印退出状态。遇到这样的进程退出,用户将无法理解究竟发生了什么事情。所以要参考下面这段程序配置错误时会执行的代码:
function checkConfig(config) { if (!config.host) { console.error("Configuration is missing 'host' parameter!"); process.exit(1); } }
在这种情况下,用户没会很清楚发生了什么。他们运行这个程序,将错误输出到控制台上,并且他们能够纠正这个问题。
process.exit()
方法非常强大。尽管它在程序代码中有自己的用途,但实际上绝对不应该将其引入可重用的库中。如果在库中确实发生了错误,则应抛出这个错误,以便程序可以决定应该如何处理它。
exceprion、rejection 和发出的 Error
虽然 process.exit()
很有用,但对于运行时错误,你需要使用其他工具。例如当程序正在处理 HTTP 请求时,一般来说错误不应该终止进程,而是仅返回错误响应。发生错误的位置信息也很有用,这正是应该抛出 Error
对象的地方。
Error
类的实例包含对导致错误的原因有用的元数据,例如栈跟踪信息和消息字符串。从 Error
扩展你自己的错误类是很常见的操作。单独实例化 Error
不会有太多副作用,如果发生错误则必须抛出。
在使用 throw
关键字或发生某些逻辑错误时,将引发 Error
。发生这种情况时,当前栈将会“展开”,这意味着每个函数都会退出,直到一个调用函数将调用包装在 try/catch
语句中为止。遇到此语句后,将调用 catch
分支。如果错误没有被包含在 try/catch
中,则该错误被视为未捕获。
虽然你应该使用带有 Error
的 throw
关键字,例如 throw new Error('foo')
,但从技术上讲,你可以抛出任何东西。一旦抛出了什么东西,它就被认为是一个例外。抛出 Error
实例非常重要,因为捕获这些错误的代码很可能会期望得到错误属性。
Node.js 内部库中常用的另一种模式是提供一个 .code
属性,该属性是一个字符串值,在发行版之间应保持一致。比如错误的 .code
值是 ERR_INVALID_URI
,即使是供人类可读的 .message
属性可能会更改,但这个 code
值也不应被更改。
可悲的是,一种更常用的区分错误的模式是检查 .message
属性,这个属性通常是动态的,因为可能回需要修改拼写错误。这种方法是很冒险的,也是容易出错的。 Node.js 生态中没有完美的解决方案来区分所有库中的错误。
当引发未捕获的错误时,控制台中将打印栈跟踪信息,并且进程将回以退出状态 1 终止。这是此类异常的例子:
/tmp/foo.js:1 throw new TypeError('invalid foo'); ^ Error: invalid foo at Object.<anonymous> (/tmp/foo.js:2:11) ... TRUNCATED ... at internal/main/run_main_module.js:17:47
上面的栈跟踪片段表明错误发生在名为 foo.js
的文件的第 2 行第 11 列。
全局的 process
是一个事件发射器,可以通过侦听 uncaughtException
事件来拦截未捕获的错误。下面是一个使用它的例子,在退出前拦截错误以发送异步消息:
const logger = require('./lib/logger.js'); process.on('uncaughtException', (error) => { logger.send("An uncaught exception has occured", error, () => { console.error(error); process.exit(1); }); });
Promise 拒绝与抛出错误非常相似。如果 Promise 中的 reject()
方法被调用,或者在异步函数中引发了错误,则 Promise 可以拒绝。在这方面,以下两个例子大致相同:
Promise.reject(new Error('oh no')); (async () => { throw new Error('oh no'); })();
这是输出到控制台的消息:
(node:52298) UnhandledPromiseRejectionWarning: Error: oh no at Object.<anonymous> (/tmp/reject.js:1:16) ... TRUNCATED ... at internal/main/run_main_module.js:17:47 (node:52298) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().
与未捕获的异常不同,从 Node.js v14 开始,这些 rejection 不会使进程崩溃。在未来的 Node.js 版本中,会使当前进程崩溃。当这些未处理的 rejection 发生时,你还可以拦截事件,侦听 process
对象上的另一个事件:
process.on('unhandledRejection', (reason, promise) => {});
事件发射器是 Node.js 中的常见模式,许多对象实例都从这个基类扩展而来,并在库和程序中使用。它们非常欢迎,值得和 error 与 rejection 放在一起讨论。
当事件发射器发出没有侦听器的 error
事件时,将会抛出所发出的参数。然后将抛出出一个错误并导致进程退出:
events.js:306 throw err; // Unhandled 'error' event ^ Error [ERR_UNHANDLED_ERROR]: Unhandled error. (undefined) at EventEmitter.emit (events.js:304:17) at Object.<anonymous> (/tmp/foo.js:1:40) ... TRUNCATED ... at internal/main/run_main_module.js:17:47 { code: 'ERR_UNHANDLED_ERROR', context: undefined }
确保在你使用的事件发射器实例中侦听 error
事件,以便你的程序可以正常处理事件而不会崩溃。
信号
信号是操作系统提供的机制,用于把用数字表示的消息从一个程序发送到另一个程序。这些数字通常用等价的常量字符串来表示。例如,信号 SIGKILL
代表数字信号 9。信号可以有不同的用途,但通常用于终止程序。
不同的操作系统可以定义不同的信号,但是下面列表中的信号一般是通用的:
名称 | 编号 | 可处理 | Node.js 默认 | 信号用途 |
---|---|---|---|---|
SIGHUP | 1 | 是 | 终止 | 父终端已关闭 |
SIGINT | 2 | 是 | 终止 | 终端试图中断,按下 Ctrl + C |
SIGQUIT | 3 | 是 | 终止 | 终端试图退出,按下 Ctrl + D |
SIGKILL | 9 | 否 | 终止 | 进程被强行杀死 |
SIGUSR1 | 10 | 是 | 启动调试器 | 用户定义的信号1 |
SIGUSR2 | 12 | 是 | 终止 | 用户定义的信号2 |
SIGTERM | 12 | 是 | 终止 | 代表优雅的终止 |
SIGSTOP | 19 | 否 | 终止 | 进程被强行停止 |
如果程序可以选择实现信号处理程序,则 Handleable 一列则为是。为否的两个信号无法处理。 Node.js 默认 这一列告诉你在收到信号时,Node.js 程序的默认操作是什么。最后一个信号用途指出了信号对应的作用。
在 Node.js 程序中处理这些信号可以通过侦听 process
对象上的更多事件来完成:
#!/usr/bin/env node console.log(`Process ID: ${process.pid}`); process.on('SIGHUP', () => console.log('Received: SIGHUP')); process.on('SIGINT', () => console.log('Received: SIGINT')); setTimeout(() => {}, 5 * 60 * 1000); // keep process alive
在终端窗口中运行这个程序,然后按 Ctrl + C
,这个进程不会被终止。它将会声明已接收到 SIGINT
信号。切换到另一个终端窗口,并根据输出的进程 ID 值执行以下命令:
$ kill -s SIGHUP <PROCESS_ID>
这演示了一个程序怎样向另一个程序发送信号,并且在第一个终端中运行的 Node.js 程序中输出它所接收到的 SIGHUP
信号。
你可能已经猜到了,Node.js 也能把命令发送到其他程序。可以用下面的命令以把信号从临时的 Node.js 进程发送到你现有的进程:
$ node -e "process.kill(<PROCESS_ID>, 'SIGHUP')"
这还会在你的第一个程序中显示 SIGHUP
消息。现在,如果你想终止第一个进程,要运行下面的命令向其发送不能处理的 SIGKILL
信号:
$ kill -9 <PROCESS_ID>
这时程序应该结束。
这些信号在 Node.js 程序中经常用于处理正常的关闭事件。例如,当 Kubernetes Pod 终止时,它将向程序发送 SIGTERM
信号,之后启动 30 秒计时器。然后程序可以在这 30 秒内正常关闭自己,关闭连接并保存数据。如果该进程在此计时器后仍保持活动状态,则 Kubernetes 将向其发送一个 SIGKILL
。
更多编程相关知识,请访问:编程视频!!
以上是详解主动终止Node.js进程的几种方法的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

explorer.exe是什么进程在我们使用Windows操作系统的时候,经常会听到一个名词"explorer.exe".那么,你是否好奇这个进程到底是什么?在本文中,我们将详细解释explorer.exe是什么进程以及其功能和作用。首先,explorer.exe是Windows操作系统的一个关键进程,它负责管理和控制Windows资源管理器(Window

ccsvchst.exe是一种常见的进程文件,它是SymantecEndpointProtection(SEP)软件的一部分,而SEP则是一款由著名的网络安全公司Symantec开发的终端保护解决方案。作为该软件的一部分,ccsvchst.exe负责管理和监控SEP的相关进程。首先,我们来了解一下SymantecEndpointProtection(

在Linux系统中,僵尸进程是已经终止但仍保留在系统中的特殊进程。虽然僵尸进程不会消耗太多资源,但如果数量过多,可能会导致系统资源耗尽。本文将介绍如何正确清除僵尸进程,以确保系统的正常运行。1Linux僵尸进程子进程完成任务后,如果父进程没有及时检查状态,子进程将成为僵尸进程。子进程在等待父进程确认,完成后系统才会回收。否则,僵尸进程会继续悬挂在系统中。要检查系统中是否存在僵尸进程,可通过运行命令top来查看所有正在运行的进程及可能存在的僵尸进程。‘top’命令的结果从上图可以看到Linux中进

Linux进程优先级调整方法详解在Linux系统中,进程的优先级决定了其在系统中的执行顺序和资源分配情况。合理调整进程的优先级可以提高系统的性能和效率。本文将详细介绍Linux中如何调整进程的优先级,并提供具体的代码示例。一、进程优先级概述在Linux系统中,每个进程都有一个与之相关联的优先级。优先级的范围一般是-20到19,其中-20表示最高优先级,19表

PHP与Vue:完美搭档的前端开发利器在当今互联网高速发展的时代,前端开发变得愈发重要。随着用户对网站和应用的体验要求越来越高,前端开发人员需要使用更加高效和灵活的工具来创建响应式和交互式的界面。PHP和Vue.js作为前端开发领域的两个重要技术,搭配起来可以称得上是完美的利器。本文将探讨PHP和Vue的结合,以及详细的代码示例,帮助读者更好地理解和应用这两

为什么Linux中的进程会处于休眠状态?在Linux操作系统中,进程可能会处于休眠状态,这是由于多种不同的原因和条件造成的。进程处于休眠状态时,表示该进程暂时被挂起,无法继续执行,直到满足某种条件后才能被唤醒继续执行。接下来将详细介绍在Linux中进程进入休眠状态的几种常见情况,并通过具体的代码示例加以说明。等待I/O完成:当进程发起一个I/O操作(例如读取

在前端开发面试中,常见问题涵盖广泛,包括HTML/CSS基础、JavaScript基础、框架和库、项目经验、算法和数据结构、性能优化、跨域请求、前端工程化、设计模式以及新技术和趋势。面试官的问题旨在评估候选人的技术技能、项目经验以及对行业趋势的理解。因此,应试者应充分准备这些方面,以展现自己的能力和专业知识。

Django是一个Python编写的web应用框架,它强调快速开发和干净方法。尽管Django是一个web框架,但是要回答Django是前端还是后端这个问题,需要深入理解前后端的概念。前端是指用户直接和交互的界面,后端是指服务器端的程序,他们通过HTTP协议进行数据的交互。在前端和后端分离的情况下,前后端程序可以独立开发,分别实现业务逻辑和交互效果,数据的交
