简述node中的child_process

500 阅读2分钟

进程:程序执行的实例

阻塞:等待执行的过程中,例如程序正在进行IO操作


exec

我们可以通过exec来创建子进程,执行命令

const child_process = require('child_process')
const {exec} = child_process

exec('ls -a ./', (error, stdout, stderr) => {
  console.log(stdout)
})

exec其本质是一个流,所以我们可以对其进行进行监听

const child_process = require('child_process')
const {exec} = child_process

const streams = exec('ls -a ./')

streams.stdout.on('data', (chunk) => {
  console.log(chunk.toString())
})

上面的方法使用了回调,我们同样可以通过promise

const child_process = require('child_process')
const util = require('util')

const {exec} = child_process

const exec2 = util.promisify(exec)

exec2('ls -a ./').then((data) => {
  console.log(data.stdout)
})

exec有一个缺点,那就是命令容易被注入

const child_process = require('child_process')
const {exec} = child_process

const userInput = './ && pwd'
//userInput 被注入了

exec(`ls -a ${userInput}`, (error, stdout, stderr) => {
  console.log(stdout)
})

我们可以看到上面的代码中,userInput被 && 注入了,存在安全问题


execFile

execFile就不会存在被注入的问题,它是以数组的形式传入命令行参数的

const child_process = require('child_process')
const {execFile} = child_process

const userInput = './'

execFile(`ls`, [`-a`, userInput], (error, stdout, stderr) => {
  console.log(stdout)
})

同样的,execFile也支持promise和流

//promise
const child_process = require('child_process')
const {execFile} = child_process
const util = require('util')
const execFile2 = util.promisify(execFile)
const userInput = './'

execFile2(`ls`, [`-a`, userInput]).then((data) => {
  console.log(data.stdout)
})

//流
const child_process = require('child_process')
const {execFile} = child_process
const userInput = './'

const streams = execFile(`ls`, [`-a`, userInput])
streams.stdout.on('data', (data) => {
  console.log(data)
})

此外,execFile的还有一个可选参数(第三个参数) options 常见的可选参数为:

cwd:'c:\' (选择命令执行的目录)

env:{name:value} (设置环境变量)

shell:'' (设置shell)

maxBuffer:1024*1024 (设置最大缓存)

execFile有一个缺点,那就是有200k缓存的限制


spawn

spawn几乎和execFile一样,除了它只支持流形式,以及,他没有大小限制

const child_process = require('child_process')
const {spawn} = child_process
const userInput = './'

const streams = spawn(`ls`, [`-a`, userInput])
streams.stdout.on('data', (chunk) => {
  console.log(chunk.toString())
})

fork

fork类似于spawn,不同的是,它是专门用来执行node程序的。

fork('./child.js') === spawn('node','./child.js')

fork 有两个事件,send 和 message 可以用来实现子进程之间的通信

//父
const child_Process = require('child_process')
const {fork} = child_Process

fork('./child.js').on('message', (m) => {
  console.log(m)
})
  .send({message: 'world'})


//子
process.send({hello:'world'})
process.on('message',(m)=>{
  console.log(m)
})