spawn
- 用法与execFile方法类似
- 没有回调函数,只能通过流事件获取结果
- 没有最大200kb的限制(因为是流)
- 能用spawn的时候就不要用execFile
- 就跟读文件一样,要用流一点一点去读,而不是一下子用回调读到内存里面。
用法跟execFile差不多,所以直接改写之前的execFile例子
spawn不支持回调,所以用流的形式去打印出chunk
const child_process = require('child_process')
const {spawn} = child_process
const userInput = '.'
const streams = spawn("ls", ['-la',`${userInput}`],{
cwd:'c:\\',
env:{NODE_ENV:'development'},
maxBuffer:1024*1024
})
streams.stdout.on('data',chunk => {
console.log(chunk.toString());//chunk是二进制 所以用toString()
})
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 (父文件)
const child_process = require('child_process');
const n = child_process.fork('./child.js');
n.on('message', m => {
console.log(`父进程得到值:`, m);
});
n.send({hello: 'world'});
child.js (子文件)
setTimeout(
() => {
process.send({foo: 'bar'});
}, 2000);
process.on('message', m => {
console.log('子进程得到值:', m);
});
运行n.js
一开始 父进程向子进程发送消息,然后两秒后子进程再发信息给父进程。
但是最后,进程并没有退出,注意红色箭头。
因为父进程一直在等子进程发消息,子进程也在等父进程发消息,互相在等,它们一直在监听message,所以没有退出。然后node.js发现了这个事情,node.js也就等这两个进程都结束再结束。所以最好不要出现这种互相等的情况,容易造成进程不退出。
小结
- exec 可以创建一个进程并获取结果,但是存在注入风险
- execFile 可以创建一个进程并获取结果,但如果使用回调形式,结果最大不能超过 200kb
- spawn 可以创建一个进程并获取结果,只支持流的形式获取结果
- fork 可以创建一个 Node.js 进程并获取结果