30

[译] Node.js 核心模块---process

精通Node.js 核心模块 ---------- process 模块

原文链接: (Mastering the Node.js Core Modules - The Process Module)[https://blog.risingstack.com/mastering-the-node-js-core-modules-the-process-module/]

在这边文章中,我们将会看一看Node.jsprocess 模块 以及它提供了哪些隐藏的gems, 在你阅读完这篇文章后, 你将会更加自信的应用, 你系那个会知道你的Node.js 应用的

进程状态, 你将会更加确信地关掉这个进程,并且你也将能够更加有效地处理错误.

在新的 (精通Node.js 核心模块)[https://blog.risingstack.com/tag/mastering-the-node-js-core-modules/]系列中, 你可以学习各种不为人所知的核心模块所具有的特性, 你

可以更好的理解这些核心 模块是如何工作的, 并且评估你自己的错误.

在这篇文章中, 我们将会看一下Node.jsprocess模块, process 对象其实是一个 EventEmitter实例, 是一个全局变量, 可以给当前的nodejs进程提供信息.

在 Node.js process 模块中值得关注的 Events

因为 process 模块是一个 EventEmitter, 所以你可以订阅他的事件就像在其他的EventEmitter事件中一样, 通过使用 .on 调用:

process.on("eventName", () => {
    //do something
});

uncaughtException

这个事件将会被触发,当一个未被捕获的JavaScript 异常冒泡回事件循环机制的时候. 默认情况下, 如果没有事件的监听器被添加到 uncaughtException处理句柄上的时候, 这个进程将会

打印这个错误栈到stderr并且退出改进程. 如果你添加一个事件监听器, 那么你可以改变这个默认的行为在你自己实现的监听器中:

process.on("uncaughtException", (error) => {
    // here 1 is a file descriptor for STDERR
    fs.writeSync(1, `Caught exception: ${error}\n`);
});

在过去的一些年间,我们已经见到过很多错误的使用案例关于这个事件监听器的.当使用uncaughtException事件时, 最重要的几条建议如下:

  • 如果uncaughtException发生的时候, 你的应用正处于一个undefined状态

  • 从这个uncaughtException状态恢复, 这种操作时强烈不推荐的, 在这个时候继续去执行正常的操作时不安全的

  • 这个处理器应该被用来使用去释放已经分配的资源

  • 在这个handler中抛出的异常时不会被捕获的, 当异常出现的时候, 应用将会立即退出.

  • 应该使用一个额外的工具来管理node进程, 并且在必要的时候重启这服务, 比如在该进程crash掉的时候

unhandleRejection

想象一下, 你正在运行下面这段代码:

const fs = require("fs-extra");

fs.copy("/tmp/myfile", "/tmp/mynewfile")
    .then(() => {

        console.log("success!");        
    });

如果这个源文件不存在回怎么办呢? 答案是依赖于当前Node.js的版本, 在一些版本中(主要是在version 4 以及之前的版本中), 这个进程将会安静地退出,

并且你也只能静坐在那里,想知道发生了什么事情? 在最近的Node.js 版本中, 你将会获取到下面这种错误信息:

(node:28391) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): undefined
(node:28391) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are
 not handled will terminate the Node.js process with a non-zero exit code.

这意味着我们将会错失一些信息当我们在使用Promise去复制一个文件的时候, 错误处理函数应该写成下面这个样子:

fs.copy("/tmp/myfile", "/tmp/mynewfile")
    .then(() => {
        console.log("success");
    })
    .catch((error) => {
        console.error(error);
    });

这个没有Promise Rejection 处理函数的例子于上面的uncaughtException例子十分像, 你的Node.js 程序处于一个未知的错误状态, 更糟的是它有可能会

造成文件描述符失败以及内存泄露.

为了解决这个问题, 你可以绑定一个uncaughtRejection事件, 并且使用process.exit(1)进行退出.

我们强烈推荐 Matteo Collinamake-promises-safe包,它可以解决这个问题在最底层.

Node.js 信号事件

信号事件将会被触发, 当Node.js接受到一个POSIX信号的时候, 让我们看一下最重要的两个信号 SIGTERMSIGUSR1.

你可以在这里找到所有受支持的信号 here

SIGTERM

这个SIGTERM信号被发送给一个Node.js 进程去请求这个进程的结束. 不像 SIGKILL 信号, 这个信号可以被监听或者被进程忽略掉.

这个信号允许进程以一种优雅的方式来关闭, 通过释放调它分配的资源, 像文件句柄或者数据库连接等. 这种关闭应用的方式被称为优雅的停止.

重要的是, 下面这几步在优雅的停止的时候需要被执行:

  1. 应用收到这个终止的信号 (收到 SIGTERM)

  2. 应用通知负载均衡器, 不再接受更新的请求

  3. 应用完成所有正在处理的请求

  4. 接下来, 它将正确地释放掉所有资源(像数据库连接)

  5. 应用将会使用一个success的状态码退出程序(process.exit())

阅读更多内容关于优雅的关闭 graceful shutdown in Node.js.

SIGUSR1

在默认的POSIX标准中, SIGUSR1SIGUSR2可以被用来给那些用户定义的清醒, Node.js 选择这个事件开始内建的调试器模式. 你可以发送 SIGUSR1

信号给进程通过下列的命令:

$ kill -USR1 PID_OF_THE_NODE_JS_PROCESS

一旦你做了这个, 这个Node.js进程将会让你知道, debugger 正在运行:

Starting debugger agent.

Debugger listening on[::]:5858

通过Node.js 暴露的方法和值

process.cwd()

这个方法将会返回当前的工作目录, 对当前正在运行的Node.js进程

$ node -e 'console.log(`Current directory: ${process.cwd()}`)'

Current directory: *******

如果你需要更改这个目录, 你可以调用 process.chdir(path)来更换路径.

process.env

这个属性返回一个包含了用户环境的对象, 就像 environ一样.

如果你正在构建应用, 并且符合了应用的12因素原则, 那么你将会和依赖这个变量, 正如 配置文件中提出的, 所有的配置项

都应该被存储在用户环境中.

环境变量 是更受欢迎的一种方式, 因为它容易更改在部署的时候, 而且不用更改任何代码. 不想配置文件, 他们几乎不会被偶然的放进代码库中.

值得一提的是, 当你更改了process.env后, 它并不会相应的映射到用户环境上.

process.exit([code])

这个方法将会告诉Node.js 进程去终止这个进程, 同步的, 同时带有一个状态码. 这个调用重要的提示:

  • 它将会使得进程尽可能快地强制退出来
    • 即使一些同步操作正在操作
    • 当异步地写给STDOUTSTDERR 时, 一些日志将会丢失
  • 在大多数情况下, 并不推荐使用process.exit, 相反, 你可以通过耗尽时间循环机制来关闭.

process.kill(pid, [signal])

使用这个方法, 你可以发送任何 符合POSIX标准的信号量给任何进程, 你不仅仅可以杀死正如建议的名称的进程, 这个命令就像一个信号发送一样, 比如 kill

系统调用.

Node.js 使用的状态码

如果一切正常的话, Node.js 将会退出使用退出状态码 0. 然而, 如果进程由于一个错误退出了, 那么, 你将会获取到下列错误码中的一个:

  • 1 : 未捕获的 严重异常, 这种异常时不能被 uncaughtException 处理句柄 处理.

  • 5 : 严重错误在 V8 , 像内存分配失败这样的

  • 9 : 无效的参数, 当一个未知的可选参数被定义时, 或者没有传入一个必选参数

[译] Node.js核心模块 --- fs