Node.js中创建和管理外部进程详解_node.js(3)
var number = process.env.number;
console.log(typeof(number)); // → "string"
number = parseInt(number, 10);
console.log(typeof(number)); // → "number"
当你把这个文件保存为child.js后,就可以在这个目录下运行下面的命令:
$ node parent.js
将会看到如下的输出:
sdtou:
string
number
stderr:
可以看到,尽管父进程传递了一个数字型的环境变量,但是子进程却以字符串形式接收它(参见输出的第二行),在第三行你把这个字符串解析成了一个数字。
生成子进程
如你所见,可以使用child_process.exec()函数来启动外部进程,并在进程结束的时候调用你的回调函数,这样用起来很简单,不过也有一些缺点:
1.除了使用命令行参数和环境变量,使用exec()无法和子进程通信
2.子进程的输出是被缓存的,因此你无法流化它,它可能会耗尽内存
幸运的是,Node的child_process模块允许更细粒度的控制子进程的启动,停止,及其它常规操作。你可以在应用程序里启动一个新的子进程,Node提供一个双向的通信通道,可以让父进程和子进程相互收发字符串数据。父进程还可以有些针对子进程的管理操作,给子进程发送信号,以及强制关闭子进程。
创建子进程
你可以使用child_process.spawn函数来创建一个新的子进程,见例8-5:
例 8-5: 生成子进程。 (chapter8/05_spawning_child.js)
// 导入child_process模块的spawn函数
var spawn = require('child_process').spawn;
// 生成用来执行 "tail -f /var/log/system.log"命令的子进程
var child = spawn('tail', ['-f', '/var/log/system.log']);
上面代码生成了一个用来执行tail命令的子进程,并将“-f”和“/bar/log/system.log”作为参数。tail命令将会监控/var/log/system.og文件(如果存在的话),然后将所有追加的新数据输出到stdout标准输出流。spawn函数返回一个ChildProcess对象,它是一个指针对象,封装了真实进程的访问接口。这个例子里我们把这个新的描述符赋值给一个叫做child的变量。
监听来自子进程的数据
任何包含stdout属性的子进程句柄,都会将子进程的标准输出stdout作为一个流对象,你可以在这个流对象上绑定data事件,这样每当有数据块可用时,就会调用对应的回调函数,见下面的例子:
//将子进程的输出打印到控制台
child.stdout.on(‘data',function(data){
console.log(‘tail output: ‘ + data);
});
每当子进程将数据输出到标准输出stdout时,父进程就会得到通知并把数据打印到控制台。
除了标准输出,进程还有另外一个默认输出流:标准错误流,通常用这个流来输出错误信息。
在这个例子里,如果/var/log/system.log文件不存在,tail进程将会输出类似下面的消息:“/var/log/system.log:No such file or directory”,通过监听stderr流,父进程会在这种错误发生时得到通知。
父进程可以这样监听标准错误流:
child.stderr.on('data', function(data) {
console.log('tail error output:', data);
});
stderr属性和stdout一样,也是只读流,每当子进程往标准错误流里输出数据时,父进程就会得到通知,并输出数据。
发送数据到子进程
除了从子进程的输出流里接收数据,父进程还可以通过childPoces.stdin属性往子进程的标准输入里写入数据,以此来往子进程发送数据。
子进程可以通过process.stdin只读流来监听标准输入的数据,但是注意你首先必须得恢复(resume)标准输入流,因为它默认处于暂停(paused)状态。
例8-6将会创建一个包含如下功能的程序: