来源:Node.js

子进程

child_process子进程是Nodejs的核心API,可以用于编写前端工程化工具、处理CPU密集型应用等

1
const cp = require("child_process")

Nodejs共有7个可创建子进程的API,Sync表示同步API,没有Sync表示异步API

  1. exec:执行命令
  2. execSync:同步执行命令
  3. execFile:执行可执行文件
  4. execFileSync:同步执行可执行文件
  5. spawn:执行命令
  6. spawnSync:同步执行命令
  7. fork:创建node子进程

使用

获取Nodejs版本号:

1
2
3
4
5
6
7
// 参数1:命令名  参数2:配置项(可选) 参数3:回调函数(失败信息、标准输出流、失败输出流)
cp.exec('node -v',(err,stdout,stderr)=>{
if(err){
return err
}
console.log(stdout.toString())
})

options配置项:

1
2
3
4
5
6
7
8
9
10
11
{
cwd: "xxx" // <string> 子进程的当前工作目录
env: {} // <Object> 环境变量键值对
encoding: "utf8" // <string> 默认为 'utf8'。
shell: "process.env.ComSpec" // <string> 用于执行命令的shell,在UNIX上默认为'/bin/sh';在Windows上默认为process.env.ComSpec
timeout: 0 // <number> 超时时间,默认为 0
maxBuffer: 200*1024 // <number> stdout或stderr允许的最大字节数;默认200*1024;如果超过限制,则子进程会被终止;查看警告:maxBuffer and Unicode
killSignal: 'SIGTERM' // <string> | <integer> 默认'SIGTERM'
uid: 114 // <number> 设置该进程的用户标识
gid: 514 // <number> 设置该进程的组标识
}

execSync

如果只需要执行单次较少的shell命令,需要尽快使用结果,使用同步的execSync会更方便一点

基本用法与exec相同

1
2
const nodeVersion = cp.execSync('node -v')
console.log(nodeVersion.toString("utf-8"))

使用exec可以打开一些软件,使用铬打开百度并进入无痕模式:

1
cp.execSync("start chrome http://www.baidu.com --incognito")

execFile

适合执行可执行文件,例如node脚本、shell文件、windows的cmd脚本、posix的sh脚本

例如yajue.cmd这样的脚本

1
2
3
4
5
6
7
8
9
10
echo '开始'
# 创建文件夹test
mkdir test
# 进入test
cd ./test
# 将内容写入test.js文件
echo console.log("test114514") >test.js
echo '结束'
# 执行js
node test.js

使用execFile执行脚本文件

1
2
3
cp.execFile(path.resolve(process.cwd(),'./yajue.cmd'),null,(err,stdout)=>{
console.log(stdout.toString())
})

spawn

exec会返回一个完整的buffer,其字节上限为200k,超出这个大小就会报错;而spawn是无上限的,且因spawn返回的是流,能够边执行边返回,所以可以用于执行一些实时获取的信息

exec只能通过返回的buffer去识别完成状态,识别起来较为麻烦;spawn在执行完成后会抛出close事件监听,并返回状态码,通过状态码可以知道子进程是否顺利执行

1
2
3
4
5
6
7
8
9
10
11
//                     命令        参数 options配置
const {stdout} = cp.spawn('netstat',['-an'],{})

// 返回的数据用data事件接受
stdout.on('data',(steram)=>{
console.log(steram.toString())
})

stdout.on('close',(msg)=> {
console.log('end')
})

exec底层通过execFile实现、execFile底层通过spawn实现

一般不会用到spawnSync方法

fork

当需要进行大量计算、或有一些容易阻塞主进程操作的代码,就适合使用fork

它能创建并返回子进程,将耗时任务交给子进程,就能保证主进程通畅了

index.js:

1
2
3
4
5
6
7
8
9
10
const {fork} = require('child_process')

// fork只接收js模块,返回的testProcess是子进程
const testProcess = fork('./test.js')

testProcess.send('我是主进程')

testProcess.on("message",(data)=>{
console.log('主进程接收了消息:',data)
})

test.js:

1
2
3
4
5
process.send('我是子进程')

process.on('message',(data)=>{
console.log('子进程接收了消息:',data)
})

通过send发送消息、message接收消息,可以相互发送接收

fork底层使用IPC通道进行通讯