幸运的是,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将会创建一个包含如下功能的程序:
1.+1 应用:一个简单的应用程序,可以从标准输入接收整型,然后相加,再把相加以后的结果输出到标准输出流。这个应用作为一个简单的计算服务, 把Node进程模拟成一个可以执行特定工作的外部服务。
2.测试+1应用的客户端,发送随机整型,然后输出结果。用来演示Node进程如何生成一个子进程然后让它执行特定的任务。
用下面例8-6的代码创建一个名为plus_one.js的文件:
例 8-6: +1 应用程序(chapter8/06_plus_one.js)
复制代码 代码如下:
// 恢复默认是暂停状态的标准输入流
process.stdin.resume();
process.stdin.on('data', function(data) {
var number;
try {
// 将输入数据解析为整型
number = parseInt(data.toString(), 10);
// +1
number += 1;
// 输出结果
process.stdout.write(number + "\n");
} catch(err) {
process.stderr.write(err.message + "\n");
}
});
上面代码里,我们等待来自stdin标准输入流的数据,每当有数据可用,就假设它是个整型并把它解析到一个整型变量里,然后加1,并把结果输出到标准输出流。
可以通过下面命令来运行这个程序:
复制代码 代码如下:
$ node plus_one.js
运行后程序就开始等待输入,如果你输入一个整数然后按回车,就会看到一个被加1以后的数字被显示到屏幕上。
可以通过按Ctrl-C来退出程序。
一个测试客户端
现在你要创建一个Node进程来使用前面的“+1应用”提供的计算服务。
首先创建一个名为plus_one_test.js的文件,内容见例8-7:
例 8-7: 测试+1应用(chapter8/07_plus_one_test.js)
复制代码 代码如下: