稳定性: 3 - 稳定
Node 通过 child_process 模块提供了 popen(3) 数据流。
它能在非阻塞的方式中,通过 stdin, stdout, 和 stderr 传递数据。 (请注意,某些程序使用内部线性缓冲 I/O, 它并不妨碍 node.js,只是你发送给子进程的数据不会被立即消。) 使用 require('child_process').spawn() 或 require('child_process').fork() 创建一个子进程。这两种方法有区别,底下会解释 below. 开发过程中查看synchronous counterparts 效率会更高。
ChildProcess 是一个 EventEmitter。
子进程有三个相关的流 child.stdin,child.stdout, 和 child.stderr。他们可能和会父进程的 stdiostreams 共享, 也可作为独立的对象。 不能直接调用 ChildProcess 类,使用spawn(), exec(), execFile(), 或 fork() 方法来创建子进程的实例。
发生于:
注意,exit 事件有可能在错误发生后调用,也可能不调用,所以如果你监听这两个事件来触发函数,记得预防函数会被调用2次。
参考 ChildProcess#kill() 和ChildProcess#send()。
子进程结束的时候触发这个事件。如果子进程正常终止,则 code 为最终的退出代码,否则为 null 。如果是由 signal 引起的终止,则 signal 为字符串,否则为 null。
注意,子进程的 stdio 流可能仍为开启模式。
注意,node 为 'SIGINT' 和 'SIGTERM' 建立句柄,所以当信号来临的时候,他们不会终止而是退出。
子进程里所有 stdio 流都关闭时触发这个事件。要和 'exit' 区分开, 因为多进程可以共享一个 stdio 流。
父进程或子进程中调用.disconnect() 方法后触发这个事件。 断开后不会在互发消息,并且 .connected 属性值为 false。
通过 .send(message, [sendHandle] 传递消息。
子进程的 stdin 是 Writable Stream(可写流)。如果子进程在等待输入,它就会暂停直到通过调用 end() 来关闭。
child.stdin 是 child.stdio[0] 的缩写。这两个都指向同一个对象,或者 null。
子进程的 stdout 是 Readable Stream(可读流)。
child.stdout 是 child.stdio[1] 的缩写。 这两个都指向同一个对象,或者 null。
子进程的 stdout 是 Readable Stream(可读流)。
child.stdout 是 child.stdio[1] 的缩写。 这两个都指向同一个对象,或者 null。
子进程的管道数组和 spawn 的 stdio 里设置为 'pipe' 的内容次序相对应。
注意,流[0-2]也能分别用 ChildProcess.stdin,ChildProcess.stdout, 和 ChildProcess.stderrNote 来表示。 在下面的例子里,只有子进程的 fd 1 设置为 pipe管道,所以父进程的 child.stdio[1] 是流(stream), 数组里其他值为null。
child = child_process.spawn("ls", { stdio: [ 0, // use parents stdin for child 'pipe', // pipe child's stdout to parent fs.openSync("err.out", "w") // direct child's stderr to a file ] }); assert.equal(child.stdio[0], null); assert.equal(child.stdio[0], child.stdin); assert(child.stdout); assert.equal(child.stdio[1], child.stdout); assert.equal(child.stdio[2], null); assert.equal(child.stdio[2], child.stderr);
子进程的 PID。
例子:
var spawn = require('child_process').spawn, grep = spawn('grep', ['ssh']; console.log('Spawned child pid: ' + grep.pid); grep.stdin.end();
如果 .connected 为 false, 消息不再可用。
发送信号给子进程。如果没有参数,会发送 'SIGTERM',参见 signal(7) 里的可用的信号列表。
var spawn = require('child_process').spawn, grep = spawn('grep', ['ssh']; grep.on('close', function (code, signal) { console.log('child process terminated due to receipt of signal '+signal); }); // send SIGHUP to process grep.kill('SIGHUP');
当信号无法传递的时候会触发 'error' 事件。给已经终止的进程发送信号不会触发 'error' 事件,但是可以能引起不可预知的后果: 因为有可能 PID (进程 ID) 已经重新分配给其他进程, 信号就会被发送到新的进程里,无法想象这样会引发什么样的事情。
注意,当函数调用 kill 信号的时候,它实际并并不会杀死进程,只是发送信号给进程。
使用 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' });
子进程代码里的 process 对象拥有 send() 方法,当它通过信道接收到信息时会触发,并返回对象。
注意,父进程和子进程 send() 是同步的,不要用来发送大块的数据(可以用管道来代替,参见child_process.spawn)。
不过发送 {cmd: 'NODE_foo'} 消息是特殊情况。所有包含 NODE_ 前缀的消息都不会被触发,因为它们是 node 的内部的核心消息,它们会在 internalMessage 事件里触发,尽量避免使用这个特性。 child.send() 里的 sendHandle 属性用来发送 TCP 服务或 socket 对象给其他的进程,子进程会用接收到的对象作为 message 事件的第二个参数。 如果不能发出消息会触发 'error' 事件,比如子进程已经退出。
以下是例子:
var child = require('child_process').fork('child.js'); // Open up the server object and send the handle. var server = require('net').createServer(); server.on('connection', function (socket) { socket.end('handled by parent'); }); server.listen(1337, function() { child.send('server', server); });
子进程将会收到这个 server 对象:
process.on('message', function(m, server) { if (m === 'server') { server.on('connection', function (socket) { socket.end('handled by child'); }); } });
注意,现在父子进程共享了server,某些连接会被父进程处理,某些会被子进程处理。
dgram 服务器,工作流程是一样的,监听的是 message 事件,而不是 connection,使用 server.bind 而不是 server.listen。(目前仅支持 UNIX 平台)
以下是发送 socket 对象的例子。 他将会创建 2 个子线程,并且同时处理连接,一个将远程地址 74.125.127.100 当做 VIP 发送到一个特殊的子进程,另外一个发送到正常进程。var normal = require('child_process').fork('child.js', ['normal'];var special = require('child_process').fork('child.js', ['special'];
// Open up the server and send sockets to child var server = require('net').createServer(); server.on('connection', function (socket) { // if this is a VIP if (socket.remoteAddress === '74.125.127.100') { special.send('socket', socket); return; } // just the usual dudes normal.send('socket', socket); }); server.listen(1337);
child.js 代码如下:
process.on('message', function(m, socket) { if (m === 'socket') { socket.end('You were handled as a ' + process.argv[2] + ' person'); } });
注意,当 socket 发送给子进程后,如果这个 socket 被销毁,父进程不再跟踪它,相应的 .connections 属性会变为 null。这种情况下,不建议使用 .maxConnections 。
关闭父子进程间的所有 IPC 通道,能让子进程优雅的退出。调用这个方法后,父子进程里的.connected 标志会变为 false,之后不能再发送消息。 当进程里没有消息需要处理的时候,会触发 'disconnect' 事件。
注意,在子进程还有 IPC 通道的情况下(如 fork() ),也可以调用 process.disconnect() 来关闭它。
这些方法遵从常用的异步处理模式(比如回调,或者返回一个事件处理)。
用指定的 command 发布一个子进程, args 是命令行参数。如果忽略, args 是空数组。
第三个参数用来指定附加设置,默认值:
{ cwd: undefined, env: process.env }创建的子进程里使用 cwd 指定工作目录,如果没有指定,默认继承自当前的工作目录。 使用 env 来指定新进程可见的环境变量。默认是 process.env。>
例如,运行 ls -lh /usr, 获取 stdout, stderr, 和退出代码:
var spawn = require('child_process').spawn, ls = spawn('ls', ['-lh', '/usr']; 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); });
例如: 一个非常精巧的方法执行 'ps ax | grep ssh'
var spawn = require('child_process').spawn, ps = spawn('ps', ['ax'], grep = spawn('grep', ['ssh']; ps.stdout.on('data', function (data) { grep.stdin.write(data); }); ps.stderr.on('data', function (data) { console.log('ps stderr: ' + data); }); ps.on('close', function (code) { if (code !== 0) { console.log('ps process exited with code ' + code); } grep.stdin.end(); }); grep.stdout.on('data', function (data) { console.log('' + data); }); grep.stderr.on('data', function (data) { console.log('grep stderr: ' + data); }); grep.on('close', function (code) { if (code !== 0) { console.log('grep process exited with code ' + code); } });
stdio 可能是以下几个参数之一:
child_process.spawn() 里的 'stdio' 参数是一个数组,它和子进程的 fd 相对应,它的值如下:
例如:
var spawn = require('child_process').spawn; // Child will use parent's stdios spawn('prg', [], { stdio: 'inherit' }); // Spawn child sharing only stderr spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] }); // Open an extra fd=4, to interact with programs present a // startd-style interface. spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });
如果设置了 detached 选项, 子进程将会被作为新进程组的leader,这使得子进程可以在父进程退出后继续运行。
缺省情况下父进程会等 detached 的子进程退出。要阻止父进程等待一个这样的子进程,调用 child.unref() 方法,则父进程的事件循环引用计数中将不会包含这个子进程。 detaching 一个长期运行的进程,并重新将输出指向文件:
var fs = require('fs'), spawn = require('child_process').spawn, out = fs.openSync('./out.log', 'a'), err = fs.openSync('./out.log', 'a'); var child = spawn('prg', [], { detached: true, stdio: [ 'ignore', out, err ] });
作者:信息录入:文案编辑:视频录制:视频编辑:图片编辑:关键字修改: