child_process
中文文档:http://nodejs.cn/api/child_process.html
代码
1.js
用exec 开启一个子进程
const child_process = require('child_process')
const {exec} = child_process
//node.js的回调的特点:第一个参数都是error
exec('ls ./',(error,stdout,stderr)=>{
console.log(error);
console.log(stdout);
console.log(stderr);
})
运行结果
第一行输出 null 意思是没有错误
第二行开始就是 文件目录 是用户输出的结果(ls ./命令)
最后没有打印stderr 因为执行没有报错。
整个过程是:先执行了exec(‘ls ./‘)这个子进程, 然后再执行后面的回调,打印出了上面这些东西(运行结果)
使用目的
- 子进程的运行结果储存在系统缓存之中(最大200kb)
- 等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。
API
exec(cmd, options, fn)
- execute的缩写,用于执行bash命令
- 同步版本:execSync
const res = execSync(‘ls ./‘,()=>{})
流
返回一个流 ```javascript const streams = exec(‘ls -l ./‘)
streams.stdout.on(‘data’,(chunk)=>{ console.log(chunk); })
注意exec不是一个stream, stdout才是stream
<a name="t7ENl"></a>
## ![image.png](https://cdn.nlark.com/yuque/0/2020/png/851574/1608189490108-83189771-6397-4bb3-b29f-93e56e3896e5.png#align=left&display=inline&height=144&margin=%5Bobject%20Object%5D&name=image.png&originHeight=144&originWidth=550&size=16806&status=done&style=none&width=550)
<a name="Baewi"></a>
## Promise
因为现在是用回调的形式,用promise的话可以避免回调地狱。
- 可以使其promise化(用util.promisify)
```javascript
const child_process = require('child_process')
const util = require('util')
const {exec} = child_process
const exec2 = util.promisify(exec)
exec2('ls ./').then(data => {
console.log(data)
})
有漏洞
- 如果cmd被注入了,可能执行意外代码
- 推荐使用execFile
const exec2 = util.promisify(exec)
const userInput = '. && pwd'
exec2(`ls ./ ${userInput}`).then(data => {
console.log(data.stdout)
})
这样就会执行了 pwd命令
如果是 rm -rf / 呢? 所以exec是极其危险的。
execFile
- 执行特定的程序
- 命令行的参数要用数组形式传入,无法注入
- 同步版本:execFileSync
- 支持流
- 好处就是不会引发注入
1.js
const child_process = require('child_process')
const {execFile} = child_process
const userInput = '. && pwd'
execFile("ls", ['-la',`${userInput}`],(error,stdout)=>{
console.log(error);
console.log(stdout);
})
运行之后会直接报错,看报错原因:因为execFile接收文件路径,. && pwd 不是文件路径
所以这样就可以防止cmd注入
execFile会通过数组的形式让你传入后面的每一部分,所以你没办法传入一个 ‘&&’
options
是execFile和exec的第二个参数。
options常用的几个值:
cwd:执行的目录
env:环境变量
shell: 用什么shell执行当前命令
maxBuffer:最大缓存(如:1024*1024)
execFile("ls", ['-la',`${userInput}`],{
cwd:'c:\\',
env:{NODE_ENV:'development'},
maxBuffer:1024*1024
}, (error,stdout)=>{
console.log(error);
console.log(stdout);
})