通过 node 中的spawn()/exec()/...
生成子进程时.js,在子进程上有一个'close'
和一个'exit'
事件.
这两者的区别是什么?什么时候需要使用什么?
通过 node 中的spawn()/exec()/...
生成子进程时.js,在子进程上有一个'close'
和一个'exit'
事件.
这两者的区别是什么?什么时候需要使用什么?
在 node 之前.js 0.7.7中,子进程上只有一个"退出"事件(没有"关闭"事件).当子进程退出且所有流(stdin、stdout、stdout)关闭时,将触发此事件.
In Node 0.7.7,引入了"关闭"事件(see commit).
当子进程的stdio流关闭时,会发出"close"事件.这与"退出"事件不同,因为多个进程可能共享相同的stdio流.
如果你只是生成了一个程序,没有对stdio做任何特殊的操作,那么"退出"之后就会触发"关闭"事件.
因此,如果您只对进程终止感兴趣(例如,因为进程拥有独占资源),那么监听"退出"就足够了.
通过实验(在Node.js v7.2.0中),我发现如果子进程不使用stdio流,那么"close"事件只有在程序退出后才会触发:
// The "sleep" command takes no input and gives no output.
cp = require('child_process').spawn('sleep', ['100']);
cp.on('exit', console.log.bind(console, 'exited'));
cp.on('close', console.log.bind(console, 'closed'));
cp.stdin.end();
cp.stdout.destroy();
cp.stderr.destroy();
console.log('Closed all stdio');
setTimeout(function() {
console.log('Going to kill');
cp.kill();
}, 500);
上述产生"睡眠"输出的程序:
Closed all stdio
Going to kill
exited null SIGTERM
closed null SIGTERM
当我把第一行改成只输出,
// The "yes" command continuously outputs lines with "y"
cp = require('child_process').spawn('yes');
... 那么输出是:
Closed all stdio
exited 1 null
closed 1 null
Going to kill
类似地,当我修改生成一个只从stdin读取的程序时,
// Keeps reading from stdin.
cp = require('child_process').spawn('node', ['-e', 'process.stdin.resume()']);
或者当我从stdin读取数据并输出到stdout时,
// "cat" without arguments reads from stdin, and outputs to stdout
cp = require('child_process').spawn('cat');
之前的实验是相当人工的.下一个实验更现实一些:将一个程序传输到另一个程序,然后杀死第一个程序.
// Reads from stdin, output the input to stdout, repeat.
cp = require('child_process').spawn('bash', ['-c', 'while read x ; do echo "$x" ; done']);
cp.on('exit', console.log.bind(console, 'exited'));
cp.on('close', console.log.bind(console, 'closed'));
cpNext = require('child_process').spawn('cat');
cp.stdout.pipe(cpNext.stdin);
setTimeout(function() {
// Let's assume that it has started. Now kill it.
cp.kill();
console.log('Called kill()');
}, 500);
输出:
Called kill()
exited null SIGTERM
closed null SIGTERM
类似地,当第一个程序只读取输入而从不输出时:
// Keeps reading from stdin, never outputs.
cp = require('child_process').spawn('bash', ['-c', 'while read ; do : ; done']);
当第一个程序在不等待stdin的情况下继续输出时,行为就不同了,下一个实验显示了这一点.
// Equivalent to "yes | cat".
cp = require('child_process').spawn('yes');
cp.on('exit', console.log.bind(console, 'exited'));
cp.on('close', console.log.bind(console, 'closed'));
cpNext = require('child_process').spawn('cat');
cp.stdout.pipe(cpNext.stdin);
setTimeout(function() {
// Let's assume that it has started. Now kill it.
cp.kill();
console.log('Called kill()');
setTimeout(function() {
console.log('Expecting "exit" to have fired, and not "close"');
// cpNext.kill();
// ^ Triggers 'error' event, errno ECONNRESET.
// ^ and does not fire the 'close' event!
// cp.stdout.unpipe(cpNext.stdin);
// ^ Does not appear to have any effect.
// ^ calling cpNext.kill() throws ECONNRESET.
// ^ and does not fire the 'close' event!
cp.stdout.destroy(); // <-- triggers 'close'
cpNext.stdin.destroy();
// ^ Without this, cpNext.kill() throws ECONNRESET.
cpNext.kill();
}, 500);
}, 500);
上述程序输出以下内容,然后退出:
Called kill()
exited null SIGTERM
Expecting "exit" to have fired, and not "close"
closed null SIGTERM