Node.js API详解之 child_process

使用:require('child_process'); 来引用child_process模块。
child_process(子进程) 模块提供了衍生子进程的功能。 这个功能主要由 child_process.spawn() 函数提供。
child_process.spawn() 方法会异步地衍生子进程,且不会阻塞 Node.js 事件循环。
child_process.spawnSync() 方法则以同步的方式提供同样的功能,但会阻塞事件循环,直到衍生的子进程退出或终止。
为了方便起见,child_process 模块提供了一些同步和异步的替代方法用于 child_process.spawn() 和 child_process.spawnSync()。
注意,每个替代方法都是在 child_process.spawn() 或 child_process.spawnSync() 的基础上实现的。

child_process.exec(): 衍生一个 shell 并在 shell 上运行命令,当完成时会传入 stdout 和 stderr 到回调函数。
child_process.execSync(): child_process.exec() 的同步方法,会阻塞 Node.js 事件循环。
child_process.execFile(): 类似 child_process.exec(),但直接衍生命令,且无需先衍生一个 shell。
child_process.execFileSync(): child_process.execFile() 的同步方法,会阻塞 Node.js 事件循环。
child_process.fork(): 衍生一个新的 Node.js 进程,并通过建立一个 IPC 通讯通道来调用一个指定的模块,
该通道允许父进程与子进程之间相互发送信息。

对于某些用例,如自动化的 shell 脚本,同步的方法 可能更方便。 大多数情况下,同步的方法会明显影响性能,因为它会拖延事件循环直到衍生进程完成。
默认情况下,在 Node.js 的父进程与衍生的子进程之间会建立 stdin、stdout 和 stderr 的管道。 数据能以非阻塞的方式在管道中流通。
注意,有些程序会在内部使用行缓冲 I/O。 虽然这并不影响 Node.js,但这意味着发送到子进程的数据可能无法被立即使用。

目录:

ChildProcess 类

child_process.spawn(command[, args][, options])

说明:

child_process.spawn() 方法使用给定的 command 和 args 中的命令行参数来衍生一个新进程。
如果省略 args,则默认为一个空数组。
command:要运行的命令
args:字符串参数列表
options:包含以下配置项
cwd:子进程的工作目录, 如果没有给出,则默认继承当前的工作目录。
env:环境变量键值对
argv0:显式地设置要发给子进程的 argv[0] 的值。 默认为 command
stdio:子进程的 stdio 配置。详见:options.stdio
detached:准备将子进程独立于父进程运行。 详见:options.detached
uid:设置该进程的用户标识
gid:设置该进程的组标识
shell: 如果为 true,则在一个 shell 中运行 command。默认为 false
windowsVerbatimArguments:在UNIX上被忽略。当指定shell时自动设置为true。默认值:false。
windowsHide:隐藏进程的控制台窗口。默认值:false。
注意:不要把未经检查的用户输入传入到该函数。 任何包括 shell 元字符的输入都可被用于触发任何命令的执行。
返回一个 ChildProcess 实例

demo:

// 运行 ls -lh ./,捕获 stdout、stderr、以及退出码:
const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', './']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});


ls.on('close', (code) => {
  console.log(`子进程退出码:${code}`);
});
// stdout: total 24
// -rw-r--r--  1 xiaoqiang  staff   371B  1 18 14:32 app.js
// -rwxrwxrwx@ 1 xiaoqiang  staff    12B  1 14 20:02 client.js
// drwxr-xr-x  5 xiaoqiang  staff   160B  1 11 18:15 fsDemo
// drwxr-xr-x  4 xiaoqiang  staff   128B  1 12 18:12 pdf
// -rw-r--r--@ 1 xiaoqiang  staff     0B 12 20 17:12 stderr.log
// -rw-r--r--  1 xiaoqiang  staff     0B 12 20 17:12 stdout.log
// -rw-r--r--@ 1 xiaoqiang  staff    21B  1  7 14:34 主工程搭建
// 子进程退出码:0

const lserr = spawn('ls', ['-lh', './sss']);

lserr.stderr.on('data', (data) => {
  console.log(`stderr: ${data}`);
});
// stderr: ls: ./sss: No such file or directory

child_process.spawnSync(command[, args][, options])

说明:

child_process.spawnSync() 方法与 child_process.spawn() 基本相同,除了该方法直到子进程完全关闭后才返回。
当遇到超时且发送了 killSignal 时,则该方法直到进程完全退出后才返回结果。
注意,如果子进程拦截并处理了 SIGTERM 信号且没有退出,则父进程会一直等待直到子进程退出。
主要差别在options参数的不同:
cwd:子进程的工作目录, 如果没有给出,则默认继承当前的工作目录。
input:要作为 stdin 传给衍生进程的值。
stdio:子进程的 stdio 配置。详见:options.stdio
env:环境变量键值对
uid:设置该进程的用户标识
gid:设置该进程的组标识
timeout:进程允许运行的最大时间数,以毫秒为单位。默认为 undefined
killSignal:衍生进程将被杀死时要使用的信号值。默认为 ‘SIGTERM’。
maxBuffer:stdout 或 stderr 允许的最大字节数。 默认为 200*1024。 如果超过限制,则子进程会被终止。
encoding:用于所有 stdio 输入和输出的编码。默认为 ‘buffer’。
shell: 如果为 true,则在一个 shell 中运行 command。默认为 false
windowsVerbatimArguments:在UNIX上被忽略。当指定shell时自动设置为true。默认值:false。
windowsHide:隐藏进程的控制台窗口。默认值:false。
该同步方法返回一个对象,包含以下字段:
pid:子进程的 pid
output:stdio 输出返回的结果数组
stdout:output[1] 的内容
stderr:output[2] 的内容
status:子进程的退出码
signal:用于杀死子进程的信号
error:子进程失败或超时产生的错误对象

demo:

// 同步运行 ls -lh ./
const { spawnSync } = require('child_process');
const ls = spawnSync('ls', ['-lh', './']);

console.log(ls);
// { status: 0,
//   signal: null,
//   output:
//    [ null,
//      ,
//       ],
//   pid: 37661,
//   stdout: ,
//   stderr:  
// }

console.log(`运行结果:${ls.stdout}`);
// total 24
// -rw-r--r--  1 xiaoqiang  staff   758B  1 18 14:52 app.js
// -rwxrwxrwx@ 1 xiaoqiang  staff    12B  1 14 20:02 client.js
// drwxr-xr-x  5 xiaoqiang  staff   160B  1 11 18:15 fsDemo
// drwxr-xr-x  4 xiaoqiang  staff   128B  1 12 18:12 pdf
// -rw-r--r--@ 1 xiaoqiang  staff     0B 12 20 17:12 stderr.log
// -rw-r--r--  1 xiaoqiang  staff     0B 12 20 17:12 stdout.log
// -rw-r--r--@ 1 xiaoqiang  staff    21B  1  7 14:34 主工程搭建

console.log(`运行错误:${ls.stderr}`);

console.log(`子进程退出码:${ls.status}`);
// 子进程退出码:0

options.stdio

说明:

options.stdio 选项用于配置子进程与父进程之间建立的管道。
默认情况下,子进程的 stdin、 stdout 和 stderr 会重定向到 ChildProcess 对象上相应的 subprocess.stdin、 subprocess.stdout 和 subprocess.stderr 流。
这等同于将 options.stdio 设为 [‘pipe’, ‘pipe’, ‘pipe’]。
为了方便起见,options.stdio 可以是以下字符串之一:
‘pipe’ – 等同于 [‘pipe’, ‘pipe’, ‘pipe’] (默认)
‘ignore’ – 等同于 [‘ignore’, ‘ignore’, ‘ignore’]
‘inherit’ – 等同于 [process.stdin, process.stdout, process.stderr] 或 [0,1,2]
另外,option.stdio 的值是一个每个索引都对应一个子进程 fd 的数组。 fd 的 0、1 和 2 分别对应 stdin、stdout 和 stderr。
额外的 fd 可以被指定来创建父进程和子进程之间的额外管道。 该值是以下之一:
‘pipe’- 创建一个子进程和父进程之间的管道。
‘ipc’ – 创建一个用于父进程和子进程之间传递消息或文件描述符的 IPC 通道符。
‘ignore’ – 指示 Node.js 在子进程中忽略 fd
对象 – 共享一个指向子进程的 tty、文件、socket 或管道的可读或可写流。
正整数 – 整数值被解析为一个正在父进程中打开的文件描述符。
null, undefined – 使用默认值。

demo:

const { spawn } = require('child_process');

// 子进程使用父进程的 stdios
spawn('prg', [], { stdio: 'inherit' });

// 衍生的子进程只共享 stderr
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });

// 打开一个额外的 fd=4,用于与程序交互
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

options.detached

说明:

在 Windows 上,设置 options.detached 为 true 可以使子进程在父进程退出后继续运行。
子进程有自己的控制台窗口。 一旦启用一个子进程,它将不能被禁用。
在非 Windows 平台上,如果将 options.detached 设为 true,则子进程会成为新的进程组和会话的领导者。
注意,子进程在父进程退出后可以继续运行,不管它们是否被分离。
默认情况下,父进程会等待被分离的子进程退出。 为了防止父进程等待给定的 subprocess,可以使用 subprocess.unref() 方法。
这样做会导致父进程的事件循环不包含子进程的引用计数,使得父进程独立于子进程退出,除非子进程和父进程之间建立了一个 IPC 信道。
当使用 detached 选项来启动一个长期运行的进程时,该进程不会在父进程退出后保持在后台运行,除非提供了一个不连接到父进程的 stdio 配置。
如果父进程的 stdio 是继承的,则子进程会保持连接到控制终端。
例子,一个长期运行的进程,为了忽视父进程的终止,通过分离且忽视其父进程的 stdio 文件描述符来实现:

demo:

const { spawn } = require('child_process');

const subprocess = spawn(process.argv[0], ['child_program.js'], {
  detached: true,
  stdio: 'ignore'
});

subprocess.unref();
也可以将子进程的输出重定向到文件:
const fs = require('fs');
const { spawn } = require('child_process');
const out = fs.openSync('./out.log', 'a');
const err = fs.openSync('./out.log', 'a');

const subprocess = spawn('prg', [], {
  detached: true,
  stdio: [ 'ignore', out, err ]
});

subprocess.unref();

child_process.exec(command[, options][, callback])

说明:

child_process.exec() 衍生一个 shell,然后在 shell 中执行 command, 且缓冲任何产生的输出
command:要运行的命令,用空格分隔参数
options:包含以下配置项
cwd:子进程的工作目录, 如果没有给出,则默认继承当前的工作目录。
env:环境变量键值对
encoding:默认为 ‘utf8’
shell:用于执行命令的 shell。 在 UNIX 上默认为 ‘/bin/sh’,在 Windows 上默认为 process.env.ComSpec
timeout:默认为 0。大于0时,子进程运行超过 timeout 毫秒后,父进程就会发送由 killSignal 属性标识的信号(默认为 ‘SIGTERM’)
maxBuffer: stdout 或 stderr 允许的最大字节数。 默认为 200*1024。 如果超过限制,则子进程会被终止。
killSignal: 默认为 ‘SIGTERM’
uid:设置该进程的用户标识
gid:设置该进程的组标识
windowsHide:隐藏进程的控制台窗口。默认值:false。
callback:当进程终止时调用,并带上输出。有三个参数:error, stdout, stderr
当成功时,error 会是 null。 当失败时,error 会是一个 Error 实例。 error.code 属性会是子进程的退出码,error.signal 会被设为终止进程的信号。
除 0 以外的任何退出码都被认为是一个错误。
返回一个 实例
注意:不要把未经检查的用户输入传入到该函数。 任何包括 shell 元字符的输入都可被用于触发任何命令的执行。

demo:

const { exec } = require('child_process');
exec('echo "The \\$HOME variable is $HOME"', (error, stdout, stderr) => {
  if (error) {
    console.error(`exec error: ${error}`);
    return;
  }
  console.log(`stdout: ${stdout}`);
  console.log(`stderr: ${stderr}`);
});
// The $HOME variable is /Users/xiaoqiang

child_process.execSync(command[, options])

说明:

child_process.execSync() 方法与 child_process.exec() 基本相同,除了该方法直到子进程完全关闭后才返回。
当遇到超时且发送了 killSignal 时,则该方法直到进程完全退出后才返回结果。
注意,如果子进程拦截并处理了 SIGTERM 信号且没有退出,则父进程会一直等待直到子进程退出。
主要差别是options参数的不同:
cwd:子进程的工作目录, 如果没有给出,则默认继承当前的工作目录。
input:要作为 stdin 传给衍生进程的值
stdio:子进程的 stdio 配置。默认为 ‘pipe’。
env:环境变量键值对
encoding:默认为 ‘utf8’
shell:用于执行命令的 shell。 在 UNIX 上默认为 ‘/bin/sh’,在 Windows 上默认为 process.env.ComSpec
uid:设置该进程的用户标识
gid:设置该进程的组标识
timeout:默认为 0。大于0时,子进程运行超过 timeout 毫秒后,父进程就会发送由 killSignal 属性标识的信号(默认为 ‘SIGTERM’)
maxBuffer: stdout 或 stderr 允许的最大字节数。 默认为 200*1024。 如果超过限制,则子进程会被终止。
killSignal: 默认为 ‘SIGTERM’
windowsHide:隐藏进程的控制台窗口。默认值:false。
返回该命令的 stdout。

demo:

const { execSync } = require('child_process');
console.log( execSync('echo "The \\$HOME variable is $HOME"') );
// 

console.log( execSync('echo "The \\$HOME variable is $HOME"').toString('utf8') );
// The $HOME variable is /Users/xiaoqiang

child_process.execFile(file[, args][, options][, callback])

说明:

child_process.execFile() 函数类似 child_process.exec()
不衍生一个 shell。 而是指定的可执行的 file 被直接衍生为一个新进程,这使得它比 child_process.exec() 更高效。
它支持和 child_process.exec() 一样的选项。 由于没有衍生 shell,因此不支持像 I/O 重定向和文件查找这样的行为。

demo:

const { execFile } = require('child_process');
execFile('node', ['--version'], (error, stdout, stderr) => {
  if (error) {
    throw error;
  }
  console.log(stdout);
});
// v9.4.0

child_process.execFileSync(file[, args][, options])

说明:

child_process.execFileSync() 方法与 child_process.execFile() 基本相同,除了该方法直到子进程完全关闭后才返回。
当遇到超时且发送了 killSignal 时,则该方法直到进程完全退出后才返回结果。
注意,如果子进程拦截并处理了 SIGTERM 信号且没有退出,则父进程会一直等待直到子进程退出。
如果进程超时,或有一个非零的退出码,则该方法会抛出一个 Error,这个错误对象包含了底层 child_process.spawnSync() 的完整结果
它支持和 child_process.execSync() 一样的选项。

demo:

const { execFileSync } = require('child_process');
const nodeVer = execFileSync('node', ['--version']);
console.log(nodeVer.toString('utf8'));
// v9.4.0

child_process.fork(modulePath[, args][, options])

说明:

child_process.fork() 方法是 child_process.spawn() 的一个特殊情况,专门用于衍生新的 Node.js 进程。
跟 child_process.spawn() 一样返回一个 ChildProcess 对象。
modulePath: 要在子进程中运行的模块
args:字符串参数列表
options:
cwd:子进程的当前工作目录
env:环境变量键值对
execPath:用来创建子进程的执行路径
execArgv:要传给执行路径的字符串参数列表。默认为 process.execArgv。
silent:如果为 true,则子进程中的 stdin、 stdout 和 stderr 会被导流到父进程中,否则它们会继承自父进程, 默认: false。
stdio:进程的 stdio 配置
windowsVerbatimArguments:在UNIX上被忽略。当指定shell时自动设置为true。默认值:false。
uid:设置该进程的用户标识
gid:设置该进程的组标识
返回: ChildProcess实例
返回的 ChildProcess 会有一个额外的内置的通信通道,它允许消息在父进程和子进程之间来回传递。
衍生的 Node.js 子进程与两者之间建立的 IPC 通信信道的异常是独立于父进程的
每个进程都有自己的内存,使用自己的 V8 实例。 由于需要额外的资源分配,因此不推荐衍生大量的 Node.js 进程。
默认情况下,child_process.fork() 会使用父进程中的 process.execPath 衍生新的 Node.js 实例。

demo:

//app.js
const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.on('message', (m) => {
	console.log('父进程收到消息:', m);
});

sub_process.send({ hello: 'world' });

//sub.js
process.on('message', (m) => {
  console.log('子进程收到消息:', m);
});

process.send({ name: 'xiaoqiang', host: 'isjs.cn' });

输出:
$ node app.js
// 子进程收到消息: { hello: 'world' }
// 父进程收到消息: { name: 'xiaoqiang', host: 'isjs.cn' }

subprocess.send(message[, sendHandle[, options]][, callback])

说明:

当父进程和子进程之间建立了一个 IPC 通道时(例如,使用 child_process.fork()),
subprocess.send() 方法可用于发送消息到子进程。
message:要发送的消息
sendHandle:用于传入一个 TCP 服务器或 socket 对象给子进程。
子进程会接收对象作为第二个参数,并传给注册在 process.on(‘message’) 事件上的回调函数
options.keepOpen:一个 Boolean 值,当传入 net.Socket 实例时可用。
当为 true 时,socket 在发送进程中保持打开。 默认为 false
callback:它在消息发送之后、子进程收到消息之前被调用。
该函数被调用时只有一个参数:成功时是 null,失败时是一个 Error 对象。
如果通道已关闭,或当未发送的消息的积压超过阈值使其无法发送更多时,subprocess.send() 会返回 false。
除此以外,该方法返回 true。

当子进程是一个 Node.js 实例时,消息可以通过 process.on(‘message’) 事件接收。
注意: 消息通过JSON序列化和解析进行传递,结果就是消息可能跟开始发送的不完全一样。
Node.js 中的子进程有一个自己的 process.send() 方法,允许子进程发送消息回父进程。
当发送一个 {cmd: ‘NODE_foo’} 消息时,是一个特例。
所有在 cmd 属性里包含一个 NODE_ 前缀的都会被认为是预留给 Node.js 核心代码内部使用的,
且不会触发子进程的 process.on(‘message’) 事件。这种消息可使用 process.on(‘internalMessage’) 事件触发

message 事件

说明:

当一个子进程使用 process.send() 发送消息时会触发 ‘message’ 事件。
消息通过JSON序列化和解析传递,结果就是消息可能跟开始发送的不完全一样
传递给回调函数两个参数:message与sendHandle

subprocess.stdio

说明:

一个到子进程的管道的稀疏数组,对应着传给 child_process.spawn() 的选项中值被设为 ‘pipe’ 的 stdio。
注意,subprocess.stdio[0]、subprocess.stdio[1] 和 subprocess.stdio[2]
分别可用作 subprocess.stdin、 subprocess.stdout 和 subprocess.stderr。
在下面的例子中,只有子进程的 fd 1(stdout) 被配置为一个管道,所以只有父进程的 subprocess.stdio[1] 是一个流,数组中的其他值都是 null。

demo:

const assert = require('assert');
const fs = require('fs');
const child_process = require('child_process');

const subprocess = child_process.spawn('ls', {
  stdio: [
    0, // 使用父进程的 stdin 用于子进程
    'pipe', // 把子进程的 stdout 通过管道传到父进程 
    fs.openSync('err.out', 'w') // 把子进程的 stderr 指向一个文件
  ]
});

assert.strictEqual(subprocess.stdio[0], null);
assert.strictEqual(subprocess.stdio[0], subprocess.stdin);

assert(subprocess.stdout);
assert.strictEqual(subprocess.stdio[1], subprocess.stdout);

assert.strictEqual(subprocess.stdio[2], null);
assert.strictEqual(subprocess.stdio[2], subprocess.stderr);

subprocess.stdin

说明:

一个代表子进程的 stdin 的可写流
注意,如果一个子进程正在等待读取所有的输入,则子进程不会继续直到流已通过 end() 关闭。
如果子进程被衍生时 stdio[0] 被设为任何不是 ‘pipe’ 的值,则这会是 null。
subprocess.stdin 是 subprocess.stdio[0] 的一个别名。 这两个属性指向相同的值。

subprocess.stdout

说明:

一个代表子进程的 stdout 的可读流。
如果子进程被衍生时 stdio[1] 被设为任何不是 ‘pipe’ 的值,则这会是 null。
subprocess.stdout 是 subprocess.stdio[1] 的一个别名。 这两个属性指向相同的值。

subprocess.stderr

说明:

一个代表子进程的 stderr 的可读流。
如果子进程被衍生时 stdio[2] 被设为任何不是 ‘pipe’ 的值,则这会是 null。
subprocess.stderr 是 subprocess.stdio[2] 的一个别名。 这两个属性指向相同的值。

subprocess.pid

说明:

返回子进程的进程标识(PID)

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

console.log(sub_process.pid);
// 40046

console.log(process.pid);
// 40045

subprocess.channel

说明:

subprocess.channel 属性是当前子进程的 IPC 通道的引用。
如果当前没有 IPC 通道,则该属性为 undefined。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

console.log(sub_process.channel);
// Pipe {
//   writeQueueSize: 0,
//   buffering: false,
//   onread: [Function],
//   sockets: { got: {}, send: {} } 
// }

console.log(process.channel);
// undefined

subprocess.connected

说明:

subprocess.connected 属性表明是否仍可以从一个子进程发送和接收消息。
当 subprocess.connected 为 false 时,则不能再发送或接收的消息。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

console.log(sub_process.connected);
// true

console.log(process.connected);
// undefined

subprocess.disconnect()

说明:

关闭父进程与子进程之间的 IPC 通道,一旦没有其他的连接使其保持活跃,则允许子进程正常退出。
调用该方法后,父进程和子进程上各自的 subprocess.connected 和 subprocess.connected 属性都会被设为 false,且进程之间不能再传递消息。
当正在接收的进程中没有消息时,就会触发 ‘disconnect’ 事件。 这经常在调用 subprocess.disconnect() 后立即被触发。
注意,当子进程是一个 Node.js 实例时(例如通过 child_process.fork() 衍生的),可以在子进程内调用 process.disconnect() 方法来关闭 IPC 通道。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.disconnect();

console.log(sub_process.connected);
// false

console.log(process.connected);
// undefined

disconnect 事件

说明:

在父进程中调用 subprocess.disconnect() 或在子进程中调用 process.disconnect() 后会触发 ‘disconnect’ 事件。
断开后就不能再发送或接收信息,且 subprocess.connected 属性会被设为 false。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.on('disconnect', () => {
	console.log('子进程已关闭');
	console.log(sub_process.connected);
});

sub_process.disconnect();
// 子进程已关闭
// false

subprocess.kill([signal])

说明:

subprocess.kill() 方法向子进程发送一个信号。 如果没有给定参数,则进程会发送 ‘SIGTERM’ 信号。
如果信号没有被送达,ChildProcess 对象可能会触发一个 ‘error’ 事件。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.kill();

subprocess.killed

说明:

subprocess.killed 属性表明该子进程是否已成功接收到 subprocess.kill() 的信号。
该属性不代表子进程是否已被终止。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.kill();

console.log(sub_process.killed)
// true

close 事件

说明:

回调接收两个参数:
code: 如果子进程退出自身,则该值是退出码。
signal:子进程被终止时的信号。
当子进程的 stdio 流被关闭时会触发 ‘close’ 事件。
‘exit’ 事件不同,因为多个进程可能共享同一 stdio 流。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.on('close', (code, signal) => {
	console.log(`退出码:${code}  信号:${signal}`);
});

sub_process.kill();
// 退出码:null  信号:SIGTERM

exit 事件

说明:

回调接收两个参数:
code: 如果子进程退出自身,则该值是退出码。
signal:子进程被终止时的信号。
子进程结束后会触发 ‘exit’ 事件。 如果进程退出了,则 code 是进程的最终退出码,否则为 null。
如果进程是收到的信号而终止的,则 signal 是信号的字符串名称,否则为 null。 这两个总有一个是非空的。

demo:

const { fork } = require('child_process');
const sub_process = fork('./sub.js');

sub_process.on('exit', (code, signal) => {
	console.log(`退出码:${code}  信号:${signal}`);
});

sub_process.kill();
// 退出码:null  信号:SIGTERM

error 事件

说明:

每当出现以下情况时触发 ‘error’ 事件:
1.进程无法被衍生;
2.进程无法被杀死;
3.向子进程发送信息失败
注意,在错误发生后,’exit’ 事件可能会也可能不会触发。
当同时监听了 ‘exit’ 和 ‘error’ 事件,谨防处理函数被多次调用。
传递给回调函数一个err,错误对象。