nodejs-Child Process模块
Child Process模块
来自《JavaScript 标准参考教程(alpha)》,by 阮一峰
目录
child_process模块用于新建子进程。子进程的运行结果储存在系统缓存之中(最大200KB),等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。
exec()
exec
方法用于执行bash命令,它的参数是一个命令字符串。
var exec = require('child_process').exec;
var ls = exec('ls -l', function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: ' + error.code);
}
console.log('Child Process STDOUT: ' + stdout);
});
上面代码的exec
方法用于新建一个子进程,然后缓存它的运行结果,运行结束后调用回调函数。
exec
方法最多可以接受两个参数,第一个参数是所要执行的shell命令,第二个参数是回调函数,该函数接受三个参数,分别是发生的错误、标准输出的显示结果、标准错误的显示结果。
由于标准输出和标准错误都是流对象(stream),可以监听data事件,因此上面的代码也可以写成下面这样。
var exec = require('child_process').exec;
var child = exec('ls -l');
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stdout: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
});
上面的代码还表明,子进程本身有close
事件,可以设置回调函数。
上面的代码还有一个好处。监听data事件以后,可以实时输出结果,否则只有等到子进程结束,才会输出结果。所以,如果子进程运行时间较长,或者是持续运行,第二种写法更好。
下面是另一个例子,假定有一个child.js文件。
// child.js
var exec = require('child_process').exec;
exec('node -v', function(error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
运行后,该文件的输出结果如下。
$ node child.js
stdout: v0.11.14
stderr:
exec方法会直接调用bash(/bin/sh
程序)来解释命令,所以如果有用户输入的参数,exec方法是不安全的。
var path = ";user input";
child_process.exec('ls -l ' + path, function (err, data) {
console.log(data);
});
上面代码表示,在bash环境下,ls -l; user input
会直接运行。如果用户输入恶意代码,将会带来安全风险。因此,在有用户输入的情况下,最好不使用exec
方法,而是使用execFile
方法。
execSync()
execSync
是exec
的同步执行版本。
它可以接受两个参数,第一个参数是所要执行的命令,第二个参数用来配置执行环境。
var execSync = require("child_process").execSync;
var SEPARATOR = process.platform === 'win32' ? ';' : ':';
var env = Object.assign({}, process.env);
env.PATH = path.resolve('./node_modules/.bin') + SEPARATOR + env.PATH;
function myExecSync(cmd) {
var output = execSync(cmd, {
cwd: process.cwd(),
env: env
});
console.log(output);
}
myExecSync('eslint .');
上面代码中,execSync
方法的第二个参数是一个对象。该对象的cwd
属性指定脚本的当前目录,env
属性指定环境变量。上面代码将./node_modules/.bin
目录,存入$PATH
变量。这样就可以不加路径,引用项目内部的模块命令了,比如eslint
命令实际执行的是./node_modules/.bin/eslint
。
execFile()
execFile方法直接执行特定的程序,参数作为数组传入,不会被bash解释,因此具有较高的安全性。
var child_process = require('child_process');
var path = ".";
child_process.execFile('/bin/ls', ['-l', path], function (err, result) {
console.log(result)
});
上面代码中,假定path
来自用户输入,如果其中包含了分号或反引号,ls程序不理解它们的含义,因此也就得不到运行结果,安全性就得到了提高。
spawn()
spawn方法创建一个子进程来执行特定命令,用法与execFile方法类似,但是没有回调函数,只能通过监听事件,来获取运行结果。它属于异步执行,适用于子进程长时间运行的情况。
var child_process = require('child_process');
var path = '.';
var ls = child_process.spawn('/bin/ls', ['-l', path]);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});
spawn方法接受两个参数,第一个是可执行文件,第二个是参数数组。
spawn对象返回一个对象,代表子进程。该对象部署了EventEmitter接口,它的data
事件可以监听,从而得到子进程的输出结果。
spawn方法与exec方法非常类似,只是使用格式略有区别。
child_process.exec(command, [options], callback)
child_process.spawn(command, [args], [options])
fork()
fork方法直接创建一个子进程,执行Node脚本,fork('./child.js')
相当于 spawn('node', ['./child.js'])
。与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信。
var n = child_process.fork('./child.js');
n.on('message', function(m) {
console.log('PARENT got message:', m);
});
n.send({ hello: 'world' });
上面代码中,fork方法返回一个代表进程间通信管道的对象,对该对象可以监听message事件,用来获取子进程返回的信息,也可以向子进程发送信息。
child.js脚本的内容如下。
process.on('message', function(m) {
console.log('CHILD got message:', m);
});
process.send({ foo: 'bar' });
上面代码中,子进程监听message事件,并向父进程发送信息。
send()
使用 child_process.fork() 生成新进程之后,就可以用 child.send(message, [sendHandle]) 向新进程发送消息。新进程中通过监听message事件,来获取消息。
下面的例子是主进程的代码。
var cp = require('child_process');
var n = cp.fork(__dirname + '/sub.js');
n.on('message', function(m) {
console.log('PARENT got message:', m);
});
n.send({ hello: 'world' });
下面是子进程sub.js代码。
process.on('message', function(m) {
console.log('CHILD got message:', m);
});
process.send({ foo: 'bar' });
参考链接
- Lift Security Team, Avoiding Command Injection in Node.js: 为什么execFile()的安全性高于exec()
- Krasimir Tsonev, Node.js: managing child processes
- byvoid, Node.js中的child_process及进程通信: exec()、execFile()、fork()、spawn()四种方法的简介
版权声明 | last modified on 2014-05-24
nodejs-Child Process模块的更多相关文章
- node中非常重要的process对象,Child Process模块
node中非常重要的process对象,Child Process模块Child Process模块http://javascript.ruanyifeng.com/nodejs/child-proc ...
- Child Process模块
目录 exec() execSync() execFile() spawn() fork() send() 参考链接 child_process模块用于新建子进程.子进程的运行结果储存在系统缓存之中( ...
- nodejs child process
//Create child processvar thread = require('child_process'); var msg = thread.fork(__dirname + '/chi ...
- nodejs的process模块如何获取其他进程的pid
var cmd=process.platform=='win32'?'tasklist':'ps aux'; var exec = require('child_process').exec; var ...
- nodejs(一)process模块
1.process是一个全局进程,你可以直接通过process变量直接访问它. process实现了EventEmitter接口,exit方法会在当进程退出的时候执行.因为进程退出之后将不再执行事件循 ...
- 在nodejs中创建child process
目录 简介 child process 异步创建进程 同步创建进程 在nodejs中创建child process 简介 nodejs的main event loop是单线程的,nodejs本身也维护 ...
- Child Process
Child Process child_process 这个模块可以生成一个子进程.nodejs提供了好几个API,本质上都是调用child_process.spawn(): const spawn ...
- nodejs——网络编程模块
net模块提供了一个异步网络包装器,用于TCP网络编程,它包含了创建服务器和客户端的方法.dgram模块用于UDP网络编程. 参考链接:https://nodejs.org/api/net.html, ...
- 关于Nodejs的多进程模块Cluster
关于Nodejs的多进程模块Cluster 前述 我们都知道nodejs最大的特点就是单进程.无阻塞运行,并且是异步事件驱动的.Nodejs的这些特性能够很好的解决一些问题,例如在服务器开发中,并 ...
随机推荐
- 转移指令原理和Inline Hook
目录 转移指令原理和Inline Hook 转移指令 操作符offset jmp指令 根据位移进行转移的jmp指令 插播HOOK知识 Inline Hook Inline Hook 原理 Hook代码 ...
- 策略路由——使用Router-Policy策略路由进行路由协议的引入
1.实验目的:实现R3-R2-R1为访问主线路,R3-R4-R1为访问备份线路 2.实验拓扑及IP,如图; 3.基本配置(端口IP) R1: <Huawei>sys[Huawei]sys ...
- 为什么Hashtab的大小通常取远离2^n 的素数
举个栗子 在Hashtab中我们通常 Hash(key) % M 来确定 key 所需要存放的位置 M就是Hashtab的大小,假设下面的两个场景 Hash(key1) = 108 Hash(key2 ...
- k8s入坑之路(4)kubenetes安装
三种安装方法: 1.kubeadm 2.kubespray 3.二进制安装 kubespray安装kubernetes集群 优点: 1.kuberspray对比kubeadm更加简洁内部集成了kube ...
- selenium2.x 与 selenium3.x 最大区别
一.selenium2.x 与 selenium3.x 最大区别 (1) 从3.0版本selenium开始使用火狐浏览器完成web自动化就需要用到驱动包了. (2) 而2.0版本的selenium使用 ...
- Maven快速入门(五)Maven的依赖管理
前面我们讲了maven项目中的最重要的文件:pom.xml 配置文件相关内容.介绍了pom 是如何定义项目,如何添加依赖的jar 包的等. 我们知道,在Maven的生命周期中,存在编译.测试.运行等过 ...
- ubuntu install redis
ubuntu install redis apt-get update apt-get install redis-server redis-server --daemonize yes
- [atARC121F]Logical Operations on Tree
(特判$n=1$的情况) 当确定权值和操作后,如何判定是否合法-- 考虑一个度为1的节点,对其权值即其对应边的边操作分类讨论: $1\or$,显然只需要最后选择这条边即可,一定合法 $1\and$或$ ...
- [atAGC045F]Division into Multiples
令$d=\gcd(a,b)$,可以发现$c|(ax+by)$等价于$lcm(c,d)|(ax+by)$,因此不妨令$c'=lcm(c,d)$,然后将$a$.$b$和$c$同时除以$d$ 接下来设$(a ...
- JVM的Xms Xmx PermSize MaxPermSize区别
Eclipse崩溃,错误提示:MyEclipse has detected that less than 5% of the 64MB of Perm Gen (Non-heap memory) sp ...