NodeJs 子进程child_process
child_process 模块提供了以与 popen(3) 类似但不完全相同的方式衍生子进程的能力。 此功能主要由 child_process.spawn() 函数提供:
1. spawn
child_process.spawn() 方法使用给定的 command 和 args 中的命令行参数衍生新进程。 如果省略,args 默认为空数组。
如果启用了 shell 选项,则请勿将未经处理的用户输入传递给此函数。 任何包含 shell 元字符的输入都可用于触发任意命令执行。
-
command<string> 要运行的命令。 -
args<string[]> 字符串参数列表。 -
options<Object>cwd<string> | <URL> 子进程的当前工作目录。env<Object> 环境变量键值对。 默认值:process.env。argv0<string> 显式设置发送给子进程的argv[0]的值。 如果未指定,这将设置为command。stdio<Array> | <string> 子进程的标准输入输出配置(参见options.stdio)。detached<boolean> 准备子进程独立于其父进程运行。 具体行为取决于平台,参见options.detached。uid<number> 设置进程的用户标识(参见setuid(2))。gid<number> 设置进程的群组标识(参见setgid(2))。serialization<string> 指定用于在进程之间发送消息的序列化类型。 可能的值为'json'和'advanced'。 有关更多详细信息,请参阅高级序列化。 默认值:'json'。shell<boolean> | <string> 如果是true,则在 shell 内运行command。 在 Unix 上使用'/bin/sh',在 Windows 上使用process.env.ComSpec。 可以将不同的 shell 指定为字符串。 请参阅 shell 的要求和默认的 Windows shell。 默认值:false(没有 shell)windowsVerbatimArguments<boolean> 在 Windows 上不为参数加上引号或转义。 在 Unix 上被忽略。 当指定了shell并且是 CMD 时,则自动设置为true。 默认值:false。windowsHide<boolean> 隐藏通常在 Windows 系统上创建的子进程控制台窗口。 默认值:false。signal<AbortSignal> 允许使用中止信号中止子进程。timeout<number> 允许进程运行的最长时间(以毫秒为单位)。 默认值:undefined。killSignal<string> | <integer> 当衍生的进程将被超时或中止信号杀死时要使用的信号值。 默认值:'SIGTERM'。
-
返回: <ChildProcess>
对于其它的方法,参数类似
1 const ps = child.spawn('ps', ['ax']); 2 const grep = child.spawn('grep', ['ssh']); 3 4 ps.stdout.on('data', (data) => { 5 grep.stdin.write(data); 6 }); 7 8 ps.stderr.on('data', (data) => { 9 console.error(`ps stderr: ${data}`); 10 }); 11 12 ps.on('close', (code) => { 13 if (code !== 0) { 14 console.log(`ps process exited with code ${code}`); 15 } 16 grep.stdin.end(); 17 }); 18 19 grep.stdout.on('data', (data) => { 20 console.log(data.toString()); 21 }); 22 23 grep.stderr.on('data', (data) => { 24 console.error(`grep stderr: ${data}`); 25 }); 26 27 grep.on('close', (code) => { 28 if (code !== 0) { 29 console.log(`grep process exited with code ${code}`); 30 } 31 });
2. exec
和spawn功能类似,用于另开进程启动shell命令。
child_process.exec() 不替换现有进程,而是使用 shell 来执行命令。
举例:让其用ts-node直接运行typescript代码
1 import * as child from 'child_process'; 2 3 child.exec('ts-node child.ts 1', ((error, stdout, stderr) => { 4 if (error) { 5 console.error(error); 6 return; 7 } 8 console.log(stdout); 9 }));
3. execfile
和exec类似,不同之处在于它默认不衍生 shell。 而是,指定的可执行文件 file 直接作为新进程衍生,使其比 child_process.exec() 略有效率。
有args参数可以传类型为Array[string]的参数
1 import * as child from 'child_process'; 2 3 child.execFile('ts-node', ['child.ts'], ((error, stdout, stderr) => { 4 if (error) { 5 console.error(error); 6 return; 7 } 8 console.log(stdout); 9 }));
4. fork
用于另开进程执行javascript脚本,直接传js路径
1 import * as child from 'child_process'; 2 3 const c1 = child.fork('child.js', ['2'], { 4 silent: false, 5 }); 6 7 const c2 = child.fork('child.js',['3'], { 8 silent: false, 9 });
5. sync
每个方法都有对应的sync版本,nodejs执行时会阻塞直至子进程完全退出
6. 事件
'close' 事件
在进程已结束并且子进程的标准输入输出流已关闭之后,则触发 'close' 事件。 这与 'exit' 事件不同,因为多个进程可能共享相同的标准输入输出流。 'close' 事件将始终在 'exit' 或 'error'(如果子进程衍生失败)已经触发之后触发。
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 close all stdio with code ${code}`);
});
ls.on('exit', (code) => {
console.log(`child process exited with code ${code}`);
});
'disconnect' 事件
调用父进程中的 subprocess.disconnect() 方法或子进程中的 process.disconnect() 方法后会触发 'disconnect' 事件。 断开连接后就不能再发送或接收消息,且 subprocess.connected 属性为 false。
'error' 事件
'error' 事件在以下情况下触发:
- 无法衍生该进程,或
- 进程无法终止,或
- 向子进程发送消息失败。
发生错误后,'exit' 事件可能会也可能不会触发。 在监听 'exit' 和 'error' 事件时,防止多次意外调用句柄函数。
另见 subprocess.kill() 和 subprocess.send()。
'exit' 事件
'exit' 事件在子进程结束后触发。 如果进程退出,则 code 为最终的进程退出码,否则为 null。 如果进程因收到信号而终止,则 signal 是信号的字符串名称,否则为 null。 两者之一将始终是非 null。
当 'exit' 事件被触发时,子进程标准输入输出流可能仍处于打开状态。
Node.js 为 SIGINT 和 SIGTERM 建立信号句柄,且 Node.js 进程不会因为收到这些信号而立即终止。 而是,Node.js 将执行一系列清理操作,然后重新触发已处理的信号。
参见 waitpid(2)。
'message' 事件
message<Object> 解析的 JSON 对象或原始值。sendHandle<Handle>net.Socket或net.Server对象、或未定义。
当子进程使用 process.send() 发送消息时,则触发 'message' 事件。
消息经过序列化和解析。 结果消息可能与最初发送的消息不同。
如果在衍生子进程时将 serialization 选项设置为 'advanced',则 message 参数可以包含 JSON 无法表示的数据。 有关更多详细信息,请参阅高级序列化。
'spawn' 事件
一旦子进程衍生成功,则会触发 'spawn' 事件。 如果子进程没有衍生成功,则不会触发 'spawn' 事件,而是触发 'error' 事件。
如果触发,则 'spawn' 事件在所有其他事件之前,且在通过 stdout 或 stderr 接收任何数据之前。
无论在衍生的进程内是否发生错误,'spawn' 事件都会触发。 例如,如果 bash some-command 衍生成功,则 'spawn' 事件将触发,尽管 bash 可能衍生 some-command 失败。 当使用 { shell: true } 时,此注意事项也适用。

浙公网安备 33010602011771号