Nodejs之child_process

child_process

child_process提供了衍生子进程的能力。

node单线程的问题就是会导致无法充分利用CPU等资源,通过child_process实现子进程,从而实现1个主进程(master),多个子进程的模式(工作进程)。

创建异步的子进程
  • child_process.exec(command[, options][, callback])
    执行的是非node程序,是一个shell命令,执行结果以回调的形式返回。

    【注意】
    1、command 是一个 shell 命令的字符串,一般是 shell 内置的 命令或shell脚本组成的文件,如 ls、cat、start.sh等,包含了命令的参数;
    2、可以使用 callback;
    3、执行成功,error为null;失败,error为Error的实例,error.code为错误码;
    4、若timeout大于0,则当子进程运行超过timeout毫秒,会给进程发送killSignal指定的信号;

    1. 回调函数
    const { exec } = require('child_process');
    exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => {
      if (error) {
        console.error(`执行的错误: ${error}`);
        return;
      }
      console.log(`stdout: ${stdout}`);
      console.error(`stderr: ${stderr}`);
    });
    
    2. Promise
    const util = require('util');
    const exec = util.promisify(require('child_process').exec);
    
    async function lsExample() {
      const { stdout, stderr } = await exec('ls');
      console.log('stdout:', stdout);
      console.error('stderr:', stderr);
    }
    lsExample();
    
  • child_process.execFile(file[, args][, options][, callback])
    执行的是非node程序,是一个可执行文件或应用,执行结果以回调的形式返回。

    【注意】
    1、比exec更高效,更安全;
    2、命令的参数只能作为第二个参数传递;
    3、默认情况下不会衍生 shell(和exec的最大差别),指定的可执行 file 直接作为新进程衍生;
    3、file 是要运行的可执行文件的名称或路径,如 node.exe,不能是 start.js 这种脚本文件;
    4、不支持I/O重定向,文件glob等;

    1. 回调函数
    const { execFile } = require('child_process');
    const child = execFile('node', ['--version'], (error, stdout, stderr) => {
      if (error) {
        throw error;
      }
      console.log(stdout);
    });
    
    2. Promise
    const util = require('util');
    const execFile = util.promisify(require('child_process').execFile);
    async function getVersion() {
      const { stdout } = await execFile('node', ['--version']);
      console.log(stdout);
    }
    getVersion();
    
  • child_process.spawn(command[, args][, options])
    执行的是非node程序,是一个shell命令,不需要获取执行结果,执行结果以流的形式返回。

    【注意】
    1、 使用给定的 command 衍生一个新进程,并带上 args 中的命令行参数,默认是空数组;
    2、以流的形式,可以减少内存占用提高输入输出效率;

    1. 检查失败的spawn
    const { spawn } = require('child_process');
    const subprocess = spawn('bad_command');
    
    subprocess.on('error', (err) => {
      console.error('启动子进程失败');
    });
    
    2. 运行ls -lh /usr,并捕获stdout、stderr、退出码
    const { spawn } = require('child_process');
    const ls = spawn('ls', ['-lh', '/usr']);
    
    ls.stdout.on('data', (data) => {
      console.log(`stdout: ${data}`);
    });
    
    ls.stderr.on('data', (data) => {
      console.error(`stderr: ${data}`);
    });
    
    ls.on('close', (code) => {
      console.log(`子进程退出,退出码 ${code}`);
    });
    
  • child_process.fork(modulePath[, args][, options])
    执行的是node程序,是一个.js文件,不需要获取执行结果,执行结果以流的形式返回,fork出来的进程一定是node进程。

    【注意】
    1、专门用于衍生新的 node进程;
    2、返回子进程ChildProcess对象,并内置为一个额外的IPC通信通道,允许消息在父进程和子进程之间来回传递,子进程独立于父进程;
    3、modulePath 要在node子进程中运行的模块,由于是 node.js 的进程,所以可以是 .js 文件;
    4、无回调,参数要以第二个参数传入;

通过process.on('message')和process.send()的机制来接收和发送消息
child.js
process.on('message',function(msg){
   process.send(msg)
})

parent.js
let cp=require('child_process');
let child=cp.fork('./child');
child.on('message',function(msg){
  console.log('got a message is',msg);
});
child.send('hello world');

// child.disconnect() 父进程中调用, 断开父子间IPC通信

// got a message is hello world


ChildProcess类

1、childProcess的实例代表衍生的子进程;
2、每个实例都有stdout、stdin、stderr三个流对象;

  • subprocess.stderr 子进程的stderr可读流,subprocess.stderr 是 subprocess.stdio[2] 的别名。 两个属性都将会指向相同的值;

  • subprocess.stdin 子进程的stdin的可写流,subprocess.stdin 是 subprocess.stdio[0] 的别名。 两个属性都将会指向相同的值;

  • subprocess.stdio 一个到子进程的稀疏数组,subprocess.stdio[0]、 subprocess.stdio[1] 和 subprocess.stdio[2] 也分别可用作 subprocess.stdin、 subprocess.stdout 和 subprocess.stderr;

  • subprocess.stdout 子进程的stdout的可读流,subprocess.stdout 是 subprocess.stdio[1] 的别名。 两个属性都将会指向相同的值;

3、通过fork产生的子进程与父进程可以用send即监听message来相互通信;
4、事件:error、close、message、exit、disconnect

  • close当子进程的stdio流已被关闭时会触发close事件;
  • disconnect断开连接,不再发送或接收消息;
  • error出现情况有4中:
    1)无法衍生进程;
    2)无法杀死进程;
    3)向子进程发送消息失败;
  • exit子进程结束后退出,但子进程的stdio流可能仍然是打开的;
  • message子进程使用process.send()发送消息时会触发message事件;
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值