child_process
中文文档:http://nodejs.cn/api/child_process.html
代码
1.js
用exec 开启一个子进程
const child_process = require('child_process')const {exec} = child_process//node.js的回调的特点:第一个参数都是errorexec('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>## <a name="Baewi"></a>## Promise因为现在是用回调的形式,用promise的话可以避免回调地狱。- 可以使其promise化(用util.promisify)```javascriptconst child_process = require('child_process')const util = require('util')const {exec} = child_processconst 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_processconst 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);})
