源代码: lib/child_process.js
child_process 模块提供了以与 popen(3) 类似但不完全相同的方式衍生子进程的能力。 此功能主要由 child_process.spawn() 函数提供:
const { spawn } = require('child_process');
const ls = spawn('ls',['-lh','/usr']);
ls.stdout.on('data',(data) => {
console.log(`stdout: ${data}`); //注意是反引号
});
ls.on('close',(code) => {
console.log(`child process exited with code ${code}`); //注意是反引号
});
默认情况下,会在父 Node.js 进程和衍生的子进程之间建立 stdin、stdout 和 stderr 的管道。 这些管道的容量有限(且特定于平台)。 如果子进程在没有捕获输出的情况下写入标准输出超过该限制,则子进程会阻塞等待管道缓冲区接受更多数据。 这与 shell 中管道的行为相同。 如果不使用输出,则使用 { stdio: ‘ignore’ } 选项
如果在 options 对象中有 options.env.PATH 环境变量,则使用其执行命令查找。 否则,使用 process.env.PATH。
在 Windows 上,环境变量不区分大小写。 Node.js 按字典顺序对 env 键进行排序,并使用不区分大小写匹配的第一个键。 只有第一个(按字典顺序)条目将传给子流程。 当传给 env 选项的对象具有多个相同键名的变体时(例如 PATH 和 Path),在 Windows 上可能会导致出现问题。
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.execFile(): 与 child_process.exec() 类似,不同之处在于,默认情况下,它直接衍生命令,而不先衍生 shell。
- child_process.fork(): 衍生新的 Node.js 进程并使用建立的 IPC 通信通道(其允许在父子进程之间发送消息)调用指定的模块。
- child_process.execSync(): child_process.exec() 的同步版本,其将阻塞 Node.js 事件循环。
- child_process.execFileSync(): child_process.execFile() 的同步版本,其将阻塞 Node.js 事件循环。
对于某些情况,例如自动化 shell 脚本,同步的方法可能更方便。 但是,在许多情况下,由于在衍生的进程完成前会停止事件循环,同步方法会对性能产生重大影响。
异步进程的创建
child_process.spawn()、child_process.fork()、child_process.exec() 和 child_process.execFile() 方法都遵循其他 Node.js API 典型的惯用异步编程模式。
每个方法都返回 ChildProcess 实例。 这些对象实现了 Node.js EventEmitter API,允许父进程注册在子进程的生命周期中发生某些事件时调用的监听器函数。
child_process.exec() 和 child_process.execFile() 方法还允许指定可选的 callback 函数,其在子进程终止时调用。
在 Windows 上衍生 .bat 和 .cmd 文件
child_process.exec() 和 child_process.execFile() 之间区别的重要性可能因平台而异。 在 Unix 类型的操作系统(Unix、Linux、macOS)上,child_process.execFile() 可以更高效,因为它默认不衍生 shell。 但是,在 Windows 上,.bat 和 .cmd 文件在没有终端的情况下无法自行执行,因此无法使用 child_process.execFile() 启动。 在 Windows 上运行时,.bat 和 .cmd 文件可以使用具有 shell 选项集的 child_process.spawn()、使用 child_process.exec()、或通过衍生 cmd.exe 并将 .bat 或 .cmd 文件作为参数传入(这也是 shell 选项和 child_process.exec() 所做的)来调用。 在任何情况下,如果脚本文件名包含空格,则需要加上引号。
// 仅在 Windows 上...
const { spawn } = require('child_process');
const bat = spawn('cmd.exe',['/c','my.bat']);
bat.stdout.on('data',(data) => {
console.log(data.toString());
});
bat.stderr.on('data',(data) => {
console.error(data.toString());
});
bat.on('exit',(code) => {
console.log(`Child exited with code ${code}`); // 注意是反引号
});
child_process.spawn(command[, args][, options])
版本 | 变更 |
---|---|
v16.4.0 | 选项 cwd 可以是使用 file: 协议的 WHATWG URL 对象。 |
v15.13.0 | 添加了超时。 |
v15.11.0 | 添加了中止信号的杀死信号。 |
v15.6.0 | 添加了中止信号支持。 |