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事件;
更多推荐
Nodejs之child_process
发布评论