spawn

image.png

  • 用法与execFile方法类似
  • 没有回调函数,只能通过流事件获取结果
  • 没有最大200kb的限制(因为是流)
  • 能用spawn的时候就不要用execFile
    • 就跟读文件一样,要用流一点一点去读,而不是一下子用回调读到内存里面。

用法跟execFile差不多,所以直接改写之前的execFile例子
spawn不支持回调,所以用流的形式去打印出chunk

  1. const child_process = require('child_process')
  2. const {spawn} = child_process
  3. const userInput = '.'
  4. const streams = spawn("ls", ['-la',`${userInput}`],{
  5. cwd:'c:\\',
  6. env:{NODE_ENV:'development'},
  7. maxBuffer:1024*1024
  8. })
  9. streams.stdout.on('data',chunk => {
  10. console.log(chunk.toString());//chunk是二进制 所以用toString()
  11. })

image.png

fork

  • 创建一个子进程,执行node脚本
  • fork(‘./child.js’) 相当于 spawn(‘node’, [‘./child.js’])

fork相当于一个语法糖,我们一般会使用fork,因为经常使用的是js脚本,而不是bash脚本。

特点

  • 会多出一个message事件,用于父子通信
  • 会多出一个send方法

一开始说exec,然后说不要用exec,只用execFile, 因为execFile更安全。
之后又说spawn比execFile更好 因为spawn使用流,没有大小限制。
然后又说fork比spawn更好,因为我们经常使用js脚本,而不会去使用bash脚本。
所以最好用fork就好了。

例子

n.js (父文件)

  1. const child_process = require('child_process');
  2. const n = child_process.fork('./child.js');
  3. n.on('message', m => {
  4. console.log(`父进程得到值:`, m);
  5. });
  6. n.send({hello: 'world'});

child.js (子文件)

  1. setTimeout(
  2. () => {
  3. process.send({foo: 'bar'});
  4. }, 2000);
  5. process.on('message', m => {
  6. console.log('子进程得到值:', m);
  7. });

运行n.js
image.png
一开始 父进程向子进程发送消息,然后两秒后子进程再发信息给父进程。
但是最后,进程并没有退出,注意红色箭头。
因为父进程一直在等子进程发消息,子进程也在等父进程发消息,互相在等,它们一直在监听message,所以没有退出。然后node.js发现了这个事情,node.js也就等这两个进程都结束再结束。所以最好不要出现这种互相等的情况,容易造成进程不退出。

小结

  1. exec 可以创建一个进程并获取结果,但是存在注入风险
  2. execFile 可以创建一个进程并获取结果,但如果使用回调形式,结果最大不能超过 200kb
  3. spawn 可以创建一个进程并获取结果,只支持流的形式获取结果
  4. fork 可以创建一个 Node.js 进程并获取结果