如何在 Node.js 中退出

用于退出的命令是什么? (即终止 Node.js 进程)

答案

调用全局process对象的exit方法:

process.exit()

从文档:

process.exit([code])

用指定的code结束进程。如果省略,则退出使用 “成功” 代码0

要以 “失败” 代码退出:

process.exit(1);

执行节点的外壳程序应将退出代码视为 1。

从官方的nodejs.org文档中:

process.exit(code)

用指定的代码结束进程。如果省略,则退出使用 “成功” 代码 0。

要以 “失败” 代码退出:

process.exit(1);

请注意, 不建议使用process.exit([number])

调用 process.exit()将强制进程尽快退出,即使仍有异步操作尚未完全完成,包括对 process.stdout 和 process.stderr 的 I / O 操作。

在大多数情况下,实际上没有必要显式调用 process.exit()。如果事件循环中没有其他待处理的工作,则 Node.js 进程将自行退出。可以设置 process.exitCode 属性,以告知进程正常退出时要使用哪个退出代码。

例如,以下示例说明了 process.exit()方法的滥用 ,这可能导致打印到 stdout 的数据被截断并丢失:

// This is an example of what *not* to do:
if (someConditionNotMet()) {
  printUsageToStdout();
  process.exit(1);
}

这是有问题的原因是因为对 Node.js 中的 process.stdout 的写入有时是异步的,并且可能在 Node.js 事件循环的多个滴答中发生。但是,调用 process.exit()会强制该进程退出,然后再执行对 stdout 的其他写入操作。

该代码应直接设置 process.exitCode,而不是直接调用 process.exit(),并通过避免为事件循环安排任何其他工作来允许进程自然退出:

// How to properly set the exit code while letting
// the process exit gracefully.
if (someConditionNotMet()) {
  printUsageToStdout();  
  process.exitCode = 1;
}

如果您在 Unix 终端或 Windows 命令行中,并且想要退出 Node REPL,请选择...

  • 按两次Ctrl + C ,或
  • 键入.exit并按 Enter,或
  • 在行首按Ctrl + D (仅 Unix)

在命令行中, .exit是您想要的:

$ node
> .exit
$

它记录在REPL docs 中 。 REPL(Read-Eval-Print-Loop)是所谓的 Node 命令行。

在正常程序中,使用process.exit([code])

这取决于您愿意退出 node.js 进程的原因,但是无论如何, process.exit()要考虑最后一个选择 。来自文档的报价:

重要的是要注意,即使仍有尚未完成的异步操作(包括对process.stdoutprocess.stderr I / O 操作process.exit() ,调用process.exit()也会强制进程尽快退出process.stderr

在大多数情况下,实际上没有必要显式调用process.exit() 。如果事件循环中没有其他待处理的工作,则 Node.js 进程将自行退出。可以设置process.exitCode属性,以告知进程正常退出时要使用哪个退出代码。

让我们介绍一下您可能愿意退出 node.js 进程以及为什么应该避免process.exit()的可能原因:

情况 1 - 执行完成(命令行脚本)

如果脚本已结束,并且节点解释器没有退出,则表明某些异步操作仍在等待处理。此时强制使用process.exit()终止process.exit()是错误的。最好尝试了解阻止脚本以预期方式退出的原因 。解决此问题时,可以使用process.exitCode将任何结果返回给调用进程。

情况 2 - 由于外部信号(SIGINT / SIGTERM / other)而终止

例如,如果您愿意正常关闭Express应用程序。与命令行脚本不同,Express App 保持无限运行,等待新请求。 process.exit()在这里将是一个不好的选择,因为它将中断所有正在处理的请求。其中一些可能是非幂等的(UPDATE,DELETE)。客户端永远不会知道这些请求是否已在服务器端完成,这可能是客户端和服务器之间数据不一致的原因。唯一好的解决方案是告诉 http 服务器停止接受新请求,并通过server.close()等待挂起的请求完成:

var express = require('express');
var app = express();
var server = app.listen(80);

process.on( 'SIGTERM', function () {
   server.close(function () {
     console.log("Finished all requests");
   });
});

如果仍然无法退出 - 请参阅案例 1。

情况 3 - 内部错误

总是最好throw一个错误,您将获得格式正确的堆栈跟踪和错误消息。较高级别的代码始终可以决定它们是否可以处理错误( catch )或使其崩溃。另一方面, process.exit(1)将静默终止进程,并且没有机会从中恢复。它可能是process.exit()的唯一 “好处”,您可以确定该过程将被终止。

REPL (命令行)

  • ctrl + c 两次

  • 输入.exit并按 Enter

脚本文件

process.exit(code)

当没有其他异步操作挂起时,节点通常以代码 0退出。

应该使用process.exit(1)并以失败代码退出,这将使我们能够推断出该节点未正常关闭并被迫关闭。

还有其他退出代码,例如

3 - 内部 JavaScript 解析错误(非常罕见)

5-v8 JavaScript 引擎中的致命错误

9 - 无效的参数

有关完整列表,请参见节点退出代码

我有一个想要的应用程序:

  1. 向用户发送电子邮件
  2. 退出并显示错误代码

我必须将process.exit(code)挂接到exit事件处理程序,否则,由于调用process.exit(code)直接杀死异步事件,因此将不会发送邮件。

#!/usr/bin/nodejs
var mailer = require('nodemailer');
var transport = mailer.createTransport();
mail = {
  to: 'Dave Bowman',
  from: 'HAL 9000',
  subject: 'Sorry Dave',
  html: 'Im sorry, Dave. Im afraid I cant do <B>THAT</B>.'
}
transport.sendMail(mail);
//process.exit(1);
process.on('exit', function() { process.exit(1); });

正如 @Dominic 指出的那样, 抛出未捕获的错误是更好的做法,而不是调用process.exit([code])
process.exitCode = 1; throw new Error("my module xx condition failed");

退出

let exitCode = 1;
process.exit(exitCode)

有用的退出代码

1 - Catchall for general errors
2 - Misuse of shell builtins (according to Bash documentation)
126 - Command invoked cannot execute
127 - “command not found”
128 - Invalid argument to exit
128+n - Fatal error signal “n”
130 - Script terminated by Control-C
255\* - Exit status out of range