如何在Windows上正确使用node.js child_process.spawn()redirect?
我有一个干净的Windows 8.1盒子,安装了node.js(v0.10.29)。 我有两个文件中的以下testing代码:
a.js
var sub = require('child_process').spawn('node', ['b.js'], {silent: true}); sub.stdout.on("data", function (data) {console.log(data.toString());});
b.js
console.log("DEBUG 1"); console.log("DEBUG 2"); process.exit();
如果我通过执行a.ja
:
node a.js
我将在控制台输出中看到“DEBUG 1” – 但不是“DEBUG 2”。 如果我删除process.exit()
,两行将被正确显示。 这种奇怪的行为发生在fork
和spawn
。
任何提示? 相同的代码在linux上没有问题。
更新02.07.2014
看起来这不是exit()和log()之间的竞争条件,因为将其更改为纯序列会产生相同的错误:
function print(text, next) { console.log(text); next(); } print("DEBUG 1", function () { print("DEBUG 2", function () { process.exit(); }); });
更新03.07.2014
silent
没有在spawn()
文档中列出,但它的工作原理。 它在fork
文档中列出,正如我之前提到的,这个问题与fork
相同。
看来,如果我介绍了最后一个输出和process.exit()
之间的延迟,所有工作正常:
console.log("DEBUG 1"); console.log("DEBUG 2"); setTimeout(function () {process.exit();}, 10000);
但是,只有当我将输出pipe道输出到父进程时,问题才会体现出来:如果我删除了silent
,那么即使没有延迟,这两个消息也能正确显示,所以很可能是pipe道通信有问题,而不是process.exit
。
更多更新03.07.2014
在评论中推测, process.exit()
可能会终止这两个进程( a.ja
和b.ja
)。 不,它终止只产卵/分叉进程,我通过添加无限setTimeout
到a.js
,它愉快地工作后b.ja
终止,仍然没有“debugging2”行。
主要编辑清晰度:
你面对的问题是console.log('DEBUG2')
和process.end()
之间的并发事件,它们中的两个同时被调用(几乎),而process.end()
具有更高的优先级,完成后,让sub
停止听事件,所以停止DEBUG2打印:
在你的代码中:
a.js |b.js start spawn |start listen |send('DEBUG1') get DEBUG1 |send('DEBUG2') start the event |send KILL print DEBUG1 | get DEBUG2 start the event get KILL kill b.js //DEBUG2 haven t been printed
现在,如果你放慢process.end:
b.js:
console.log('DEBUG1'); console.log('DEBUG2'); setTimeout(function () { process.end(); }, 1000); a.js |b.js start spawn |start listen |send('DEBUG1') get DEBUG1 |send('DEBUG2') start the event |wait print DEBUG1 |wait get DEBUG2 |send KILL start the event print DEBUG2 get KILL kill b.js
但是这很麻烦,你不知道会有多less“等待”。 另一个解决scheme是让b.jsinheritancestdout,所以没有事件要做:
a.js:
var sub = require('child_process').spawn('node', ['b.js'], {stdio:[process.stdin, process.stdout, process.stderr]}); a.js |b.js start spawn |start listen |print DEBUG1 |print DEBUG2 |send KILL get KILL | kill b.js
现在,没有错误的代码,但是你不能得到在a.js中打印的内容。 我认为process.nextTick的另一个解决scheme可以工作,但我不知道如何工作。
编辑:
process.exit()
杀死b.js,这是预期的行为。 a.js看到data
事件结束,所以有一个空的事件循环,所以杀死自己:)