Node第十四章(子进程的使用)

292 阅读3分钟

child_process子进程

概念

  • child_process 子进程是NodeJS的核心API,如果你会 shell命令 这个API对你帮助很大,

适合做一些cpu密集的任务

创建子进程

NodeJS创建子进程有 7个API 携带 Sync是同步执行 没有Sync的是异步执行

exec

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

    • command 执行的命令 如 node -v

    • options可选参数有以下几个参数

      • cwd 指定命令在那个工作目录执行 默认值是process.cwd() 父进程的根目录

        • 假如工作目录在 D:/home/user/project
        const { exec } = require('node:child_process');
        exec('cd', {
            cwd: process.cwd() // 默认值
        },(error, stdout, stderr) => {
          if (error) {
            console.error(`exec error: ${error}`);
            return;
          }
          console.log(`stdout: ${stdout}`); // 应输出类似于 'D:/home/user/project'
          })
        
    • encoding 设置编码格式 默认是UTF8

    • timeout 设置子进程执行最大时间,超过则报超时 默认为0 即等待子进程执行完毕

    • shell 设置以什么的脚本执行shell

    • 在 Windows 系统上,默认的 shell'cmd.exe'(命令提示符)。

      • 在 Unix-like 系统上(如 Linux 和 macOS),默认的 shell'/bin/sh'

      • maxBuffer stdoutstderr 允许的最大字节数。 默认为 200*1024。 如果超过限制,则子进程会被终止

      • 举例: 如果我设置 maxBuffer 为 10Mb 当 stdout字节数是6MB 和 stderr 5MB 这样就会报错

      • killSignal 以什么样的方式退出子进程

      • 默认值SIGTERM 将子进程的东西清理完毕后 再退出进程

      • SIGINT 直接退出子进程

      • env 给子进程设置环境变量

      • gid 群组id 类似于后台管理系统的 角色

      • uid 用户id 类似于后台管理系统的 用户

    const { exec } = require('node:child_process');
    exec('cd', {
        cwd: process.cwd() // 默认值
    },(error, stdout, stderr) => {
      if (error) {
        console.error(`exec error: ${error}`);
        return;
      }
      console.log(`stdout: ${stdout}`); // 应输出类似于 'D:/home/user/project'
     });
    

/database_script.js 中,成功给子进程设置了一个环境变量

console.log(process.env) // 其中 ADATEBASE: 'http://local:8080'  ....

execSync

  • child_process.execSync(command, [options])exec 的同步任务
  • options 参数跟上面类似
const {execSync} = require('child_prcess')
const ex = execSync('dir',{});
console.log(ex.toString()); // v16.14.2

execSync("start chrome http://www.baidu.com --incognito") // 打开谷歌 无痕浏览

execFile和execFileSync

  • child_process.execFile(command, [args] [options], callback)

  • child_process.execFileSync(command, [args] [options])

  • execFile 只能执行 本身电脑能运行的文件 如 cmd

echo '开始'

mkdir test 

cd ./test

echo console.log("test1232131") >test.js

echo '结束'

node test.js

使用execFile 执行这个
execFile(path.join(process.cwd(), './bat.cmd'), (err, data) => {
  console.log('data', data);
});

注意execFile函数默认只能执行操作系统能够直接识别的可执行文件,对于像 Node.js、Java 或 Python 这样的脚本或编程语言,它们的文件(如 .js.java.py 文件)本身并不是可执行文件,而是需要相应的解释器或编译器来执行。

使用execFile 执行 .js 文件
execFile('node', [path.join(process.cwd(), './utils/index.js')], null, (err, stdout) => {
  console.log(stdout.toString()); // hello node
});
在./utils/index.js文件中
console.log('hello node')
execFileSync同步执行js文件
const item = execFileSync('node', [path.join(process.cwd(), './utils/index.js')]);
console.log('item', item.toString());// hello node

spawn和spawnSyc

为什么有spawn 他和exec,execFile 的区别是啥呢,

  • spawn 获取的实时的信息,处理返回字节数据量比较大的时候使用特别好,exec execFile会有返回大小限制 约200k 超出则会报错 这个时候使用spawn是一个明智的选择

  • spawn(command, [args] [options])

    const { stderr, stdout } = spawn('ping', ['www.baidu.com']);
    stdout.on('data', (data) => {
      console.log(data.toString());
    });
    stderr.on('data',(err)=>{
        console.log('报错',err)
    })
    
  • spawn也可以处理文件

    • 举例使用 js文件

      const { stderr, stdout } = spawn('node', [path.join(prcocess.cwd(),'./myIndex,js'),'xxx','aaa']);
      stdout.on('data', (data) => {
        console.log(data.toString());
      });
      stderr.on('data',(err)=>{
          console.log('报错',err)
      })
      
    • myIndex,js文件中

      console.log('process.argv')// 'xxx','aaa'
      console.log('hello') // hello
      

注意exec是底层通过execFile实现 execFile底层通过spawn实现

fork开启线程

  • 适合做大量计算 会阻塞主任务的时候开启另一个线程实现

  • 如在index.js

    const child = fork(path.join(process.cwd(), './utils/child.js'));
    child.on('message', (data) => {
      console.log('data', data);
    });
    child.send('哈哈哈我是主进程');
    

    ./utils/child.js 文件中

    process.on('message', (msg) => {
      console.log(msg);
    });
    process.send('你好我是子进程');
    

    send 发送信息 ,message接收消息,可以相互发送接收。

​ fork底层使用的是IPC通道进行通讯的,