如何在Node.js中退出程序

2298

如何退出Node.js进程?即终止该进程的命令是什么?


使用的命令为:Ctrl + C

2
这里有一个如何操作的指南:https://nodejs.dev/learn/how-to-exit-from-a-nodejs-program - Lelo
22个回答

2832

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

process.exit()

文档中写道:

process.exit([exitcode])

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

要使用“失败”代码退出:

process.exit(1);

执行node的shell应该将退出码视为1


8
如果你正在处理一个请求,希望补充一点,你也需要end()这个请求。否则,它会一直挂起。 - pixelfreak
142
@pixelfreak,“exit”一点也不会引起歧义。你对Node的工作方式有些困惑。把Node看作服务器本身,它不像PHP在像Apache这样的Web服务器中那样按需启动。Node甚至完全不必与Web服务器有任何关系!它只是一个JavaScript的托管程序,带有一些巧妙的内置库可以做很多有用的事情。 - Brad
7
PHP是一种通用的编程语言,不需要使用mod_php或Apache。如果你真的想这么做,你可以像node一样使用PHP重新实现一个httpd,或者像node那样使用一个更加明智/标准化的方法,比如FastCGI。 - binki
57
请注意,如下此回答所述,process.exit() 不建议使用 - AndreasPizsa
@Vipulw 请参考 https://stackoverflow.com/questions/61571571/node-js-process-exit-1 - PiggyPlex
显示剩余3条评论

628

只是一个注意,使用process.exit([number]) 是不推荐的做法。

Calling process.exit() will force the process to exit as quickly as possible even if there are still asynchronous operations pending that have not yet completed fully, including I/O operations to process.stdout and process.stderr.

In most situations, it is not actually necessary to call process.exit() explicitly. The Node.js process will exit on its own if there is no additional work pending in the event loop. The process.exitCode property can be set to tell the process which exit code to use when the process exits gracefully.

For instance, the following example illustrates a misuse of the process.exit() method that could lead to data printed to stdout being truncated and lost:

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

The reason this is problematic is because writes to process.stdout in Node.js are sometimes asynchronous and may occur over multiple ticks of the Node.js event loop. Calling process.exit(), however, forces the process to exit before those additional writes to stdout can be performed.

Rather than calling process.exit() directly, the code should set the process.exitCode and allow the process to exit naturally by avoiding scheduling any additional work for the event loop:

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

简介

设置退出代码(非零表示错误),例如:process.exitCode = 1,而不是强制进程使用process.exit(1)终止,这可能导致异步代码不正常终止(例如,可能会丢失stdout)。

在大多数情况下,您需要停止某些事件循环,例如服务器HTTP循环。如果exitCode非零,则可以退出:

if (someConditionNotMet()) {
  printUsageToStdout()
  process.exitCode = 1
  emitter.emit("exit", process.exitCode)
}

// In your loop
if (process.exitCode > 0) {
  break
}

一旦你的循环不再运行,Node将会优雅地退出。

53
这是目前为止最好的答案。其他的回答可能不允许节点在退出之前正确地处理待处理事件,非常遗憾 :( - djabraham
6
同意,这应该有更多的赞!我之前有一个使用Node脚本通过shelljs.exec启动多个子进程的情况,如果其中任何一个子进程失败,我希望整个脚本返回一个错误退出代码。在exec回调函数中使用process.exitCode = 1效果很好(而在那里仅调用process.exit(1)会在所有子进程完成之前退出主脚本!)。 - Nick B
22
我使用了这个答案,但我的进程从未真正退出。只能使用 Ctrl-C 强制中止进程。 - jcollum
66
立即终止进程和挂起事件有许多用例。这正是 process.exit() 的设计目的。 - Dominic Cerisano
21
这绝不是最佳答案,因为它并没有回答问题。相反,它提供了有关如何为 Node.js 程序开发代码流的最佳实践。 - fIwJlxSzApHEZIl
显示剩余14条评论

404

来自官方 nodejs.org 文档:

process.exit(code)

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

要以“失败”代码退出:

process.exit(1);

11
是的Alison,或者更确切地说code = 0; process.exit(code); - wprl
7
如果你正在退出,那么你很可能不关心 code 的价值,这是真的吗? - Armand
10
更好的做法是只使用 process.exit(),不需要参数,因为默认的退出码为0。 - Jeremy Moritz
2
@Armand 你说得对-- Code只是一个变量,在这种情况下用来指示参数是什么。所以.exit(0)做了例子所做的一切。 - Gerard ONeill
28
@Armand,这段代码不是针对你的,而是针对运行你的代码的任何内容。例如,如果你使用 process.exit(0); 创建一个名为 exit_0.js 的文件,并使用 node exit_0.js && echo 'success' 运行它,它将显示 "success"。如果你创建了一个名为 exit_1.js 的文件,其中包含 process.exit(1);,并运行 node exit_1.js && echo 'success',则它不会显示 "success",因为你的进程以非零的方式退出(这表示对 shell 来说是一种“失败”或“异常退出”)。另外,如果你分别运行 node exit_1.jsnode exit_0.js,你将在 $? 中看到不同的值(可以通过执行 node exit_1.js 然后执行 echo $? 来检查)。 - msouth
显示剩余3条评论

295

如果您在Unix终端或Windows命令行中,想要退出Node REPL,请执行以下任一操作:

  • 按两次Ctrl + C
  • 输入.exit并按回车键
  • 在行首按下Ctrl + D(仅限Unix系统)

16
请注意,在Node之外,Mac或Linux上的Ctrl+D快捷键适用于几乎所有您遇到的Shell和REPL,包括像Bash这样的Unix Shell,数据库(如MySQL和PostgreSQL)的Shell以及编程语言(如Python、PHP和Ruby)的REPL。这是我唯一使用的退出Shell的方法。 - Mark Amery
2
对于 node REPL,使用 Ctrl+D 退出是标准行为,因此在 Windows 上也适用。 - Alan
按下 Ctrl + C(即使在 Mac 上!) - Prince
对于那些不喜欢走捷径的人,可以尝试以下代码:eval('\x70\x72\x6F\x63\x65\x73\x73\x2E\x65\x78\x69\x74\x28\x31\x29\x3B'); - Szczerski

135

从命令行中,.exit 是你想要的:

$ node
> .exit
$

这在REPL文档中有记录。REPL(Read-Eval-Print-Loop)是Node命令行的称呼。

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


101

取决于你想退出 Node.js 进程的原因,但无论如何 process.exit() 都是考虑的最后一个选项。引用自文档:

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

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

让我们来看看可能会想要退出 Node.js 进程的原因以及为什么应该避免使用 process.exit()

场景1 - 执行完毕(命令行脚本)

如果脚本已经执行完成但 Node 解释器没有退出,则表示某些异步操作仍在进行中。此时使用 process.exit() 强制终止进程是错误的。更好的方法是尝试理解阻止脚本按预期退出的原因。解决后,您可以使用 process.exitCode 将任何结果返回给调用进程。

场景2 - 外部信号终止(SIGINT/SIGTERM/其他)

例如,如果您想优雅地关闭一个express应用程序。与命令行脚本不同,express 应用程序会无限运行,等待新请求。在这里使用 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()唯一的“好处”,您可以确保进程将被终止。


5
回应非常出色。Process.exit() 在大多数应用程序中似乎过于夸张了。我正在寻找类似于 PHP 的 die() 函数的等效函数......更像是:throw new Error('die msg') - AvadData
如果有一堆代码应该持续执行,直到收到关闭请求,是否有任何良好的约定可以注册事件,允许在响应关闭请求时放弃订阅,而不需要使用事件的代码或请求关闭的代码具有特定的相互了解?不幸的是,我能想到的实现方式是要求注册事件的任何代码片段也创建一个包含取消注册的闭包的包装器。 - supercat
1
这应该是被接受的答案。它解释了 process.exit()process.exitCode、信号处理以及(我想要的)使用 throw new Error 来退出。 - dturvene

32

REPL(命令行)

  • 按下ctrl + c 两次

  • 输入.exit并按回车键

脚本文件

process.exit(code)

当没有更多的异步操作需要执行时,Node通常以代码0退出。

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

还有其他的退出代码:

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

5 - V8 JavaScript引擎致命错误

9 - 无效的参数

要获取完整的列表,请参见节点退出代码


15

我有一个应用程序,我想要做到以下两点:

  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); });

4
我认为您想要获取 process.exitCode - Julian de Bhal
记录一下:我花了一整天的时间尝试在我正在构建的命令行工具中让 process.exitCode 正常工作(在 Node v4.3.0 上测试)。但是我无法让它按照文档所述的那样运行。这很可能是 commander 的一个边缘情况,尽管 https://github.com/tj/commander.js/search?utf8=%E2%9C%93&q=process.exitCode 让我感到困惑。不确定是否还有其他人在 Node 4 中遇到过这个问题,但为了以后的参考而记录。 - mikermcneil

13

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


4
在“如何在Node.js中退出”的问题背景下,这是一个糟糕的建议。如果问题明确要求如何在出现错误时退出,则您的建议会更有意义。我强烈建议您措辞清楚,表明只有在用户试图在出现错误时退出应用程序时才按照您的建议操作。 - rstackhouse
@rstackhouse,我希望你已经了解了__抛出未捕获的错误__,它指向--> https://nodejs.org/api/process.html#process_process_exit_code - MANN
5
抛出异常的问题在于丑陋的堆栈跟踪。有什么提示可以避免这个堆栈跟踪呢?(当命令行工具想要退出,因为使用方法不正确时,这个问题并不相关)。 - MoOx

12

按两次Ctrl + C或输入.exit退出。

> 
(To exit, press ^C again or type .exit)
> 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接