Skip to content
On this page

node子进程

https://juejin.cn/post/6882290865763680264

child_process 模块提供了以下 4 个方法用于创建子进程,并且每一种方法都有对应的同步版本

  • spawn: 启动一个子进程来执行命令;
  • exec: 启动一个子进程来执行命令,与 spawn 不同的是,它有一个回调函数获知子进程的状况;
  • execFile: 启动一个子进程来执行可执行文件;
  • fork: 与 spawn 类似,不同点在于它创建 Node 的子进程只需指定要执行的 JavaScript 文件模块即可;
tsx
const cp = require('child_process');

// spawn
cp.spawn('node', ['./dir/test1.js'],
  { stdio: 'inherit' }
);
// exec
cp.exec('node ./dir/test1.js', (err, stdout, stderr) => {
  console.log(stdout);
});
// execFile
cp.execFile('node', ['./dir/test1.js'],(err, stdout, stderr) => {
  console.log(stdout);
});
// fork
cp.fork('./dir/test1.js',
  { silent: false }
);

// ./dir/test1.js
console.log('test1 输出...');

差异列表如下:

类型回调/异常进程类型执行类型可设置超时
spawn不支持任意命令不支持
exec支持任意命令支持
execFile支持任意可执行文件支持
fork不支持NodeJavaScript 文件不支持

exec

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

创建一个 shell,然后在 shell 里执行命令。执行完成后,将 stdout、stderr 作为参数传入回调方法。 options 参数说明:

  • cwd:当前工作路径;
  • env:环境变量;
  • encoding:编码,默认是 utf8;
  • shell:用来执行命令的 shell,unix 上默认是 /bin/sh,windows 上默认是 cmd.exe;
  • timeout:默认是 0;
  • killSignal:默认是 SIGTERM;
  • uid:执行进程的 uid;
  • gid:执行进程的 gid;
  • maxBuffer: 标准输出、错误输出最大允许的数据量(单位为字节),如果超出的话,子进程就会被杀死;默认是 200*1024(即 200k )
typescript
exec('ls', {cwd: __dirname + '/dir'}, (error, stdout, stderr) => {
  if (error) {
    console.error('error:', error);
    return;
  }
  console.log('stdout: ' + stdout);
  console.log('stderr: ' + stderr);
})

// 子进程输出/错误监听
const child = exec('node ./dir/test1.js')

child.stdout.on('data', data => {
  console.log('stdout 输出:', data);
})
child.stderr.on('data', err => {
  console.log('error 输出:', err);
})

execFile

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

可以执行js 或者 sh文件

命令是放第二个参数,数组的方式传递

typescript
const { execFile } = require('child_process');

// 1、执行js
execFile('node', ['./dir/test1.js'], (error, stdout, stderr) => {
  if (error) {
    console.error('error:', error);
    return;
  }
  console.log('stdout: ' + stdout); 
  console.log('stderr: ' + stderr);
})


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

// 2、执行 shell 脚本
// 在 shell 脚本中可以访问到 process.env 的属性 
process.env.DIRNAME = __dirname;
execFile(`${__dirname}/dir/test2.sh`, (error, stdout, stderr) => {
  if (error) {
    console.error('error:', error);
    return;
  }
  console.log('stdout: ' + stdout); // stdout: 执行 test2.sh  test1 输出...
  console.log('stderr: ' + stderr);
})

// ./dir/test2.sh

#! /bin/bash
echo '执行 test2.sh'
node $DIRNAME/dir/test1.js


// ./dir/test1.js
console.log('test1 输出...');

fork

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

1)modulePath:子进程运行的模块; (2)args:字符串参数列表; (3)options 参数如下所示,其中与 exec 重复的参数就不重复介绍:

  • execPath: 用来创建子进程的可执行文件,默认是 /usr/local/bin/node。也就是说,你可通过 execPath 来指定具体的 node 可执行文件路径;(比如多个 node 版本)
  • execArgv: 传给可执行文件的字符串参数列表。默认是 process.execArgv,跟父进程保持一致;
  • silent: 默认是 false,即子进程的 stdio 从父进程继承。如果是 true,则直接 pipe 向子进程的child.stdin、child.stdout 等;
  • stdio: 选项用于配置在父进程和子进程之间建立的管道,如果声明了 stdio,则会覆盖 silent 选项的设置;

spawn

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

typescript
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-al']);

// 输出相关的数据
ls.stdout.on('data', function(data){
    console.log('data from child: ' + data);
});

// 错误的输出
ls.stderr.on('data', function(data){
    console.log('error from child: ' + data);
});

// 子进程结束时输出
ls.on('close', function(code){
    console.log('child exists with code: ' + code);
});

子进程通信

typescript
// 例子
const { fork } = require('child_process');
const child = fork('./dir/test5.js')

child.on('message', (val) => {
  console.log('message 事件:', val);
})

// ./dir/test5.js
console.log('event_test 输出...');
process.send('子进程发送给父进程的消息...')

进程间通信
// 父进程
const child3 = fork('./dir/child3_1.js');

child3.on('message', (m)=>{
  console.log('message from child: ' + JSON.stringify(m));
});

child3.send({from: 'parent'});

// 子进程
process.on('message', function(m){
  console.log('message from parent: ' + JSON.stringify(m));
});

process.send({from: 'child'});

粤ICP备2024285819号