將一個子進程的stdout用作另一個子進程的標準輸入時,似乎有時數據不會傳遞給下一個子進程:當使用一個子進程的標準輸出作爲另一個子進程的標準輸入時,數據有時不會傳遞給第二個子進程
var spawn = require('child_process').spawn;
var pipeId = 0;
var launchProcess = function(cmd, args, stdin){
return spawn(cmd, args, {
stdio: [stdin ? stdin : 'ignore', 'pipe', 'pipe']
});
};
var launch = function(){
var task0 = launchProcess('echo', ['how\nare\nyou\ndear\nstranger']);
var task1 = launchProcess('tee', ['/tmp/body-pipeline-' + pipeId], task0.stdout);
pipeId++;
task1.on('exit', launch);
};
launch();
有些文件是空的:
ls -lhS /tmp/body-pipeline-*
我也試過路過文件描述符爲正整數通過訪問task0.stdout._handle.fd
和問題仍然存在。
據我所知,shell管道是如何工作的:一個進程的stdout的同一個文件描述符被用作另一個進程的stdin。我試圖避免通過NodeJS進程傳遞所有數據,因爲當子進程輸出大量數據時,會導致CPU負載過高。
更新:當管道被同時用於標準輸入和標準輸出一切正常(使用cat這裏有較長的文本測試):
var spawn = require('child_process').spawn;
var pipeId = 0;
var launchProcess = function(cmd, args, stdin){
return spawn(cmd, args, {
stdio: [stdin ? stdin : 'pipe', 'pipe', 'pipe']
});
};
var launch = function(){
var task0 = launchProcess('cat');
var task1 = launchProcess('tee', ['/tmp/body-pipeline-' + pipeId]);
task0.stdout.pipe(task1.stdin)
task0.stdin.write(JSON.stringify(process.env).split(',').join('\n'))
task0.stdin.end();
pipeId++;
task1.on('exit', launch);
};
launch();
UPDATE2:當使用task0.stdout.pipe(task1.stdin)
腳本使用50 %的CPU(相比於0%通過task0的標準輸出作爲任務1的標準輸入時):
var spawn = require('child_process').spawn;
var pipeId = 0;
var launchProcess = function(cmd, args, stdin, stdout, stderr){
return spawn(cmd, args, {
stdio: [stdin, stdout, stderr]
});
};
var launch = function(){
var task0 = launchProcess('yes', ['lala'], 'ignore', 'pipe', 'ignore');
var task1 = launchProcess('tee', ['/tmp/body-pipeline-' + pipeId], 'pipe', 'ignore', 'ignore');
// var task1 = launchProcess('tee', ['/tmp/body-pipeline-' + pipeId], task0.stdout, 'ignore', 'ignore');
task0.stdout.pipe(task1.stdin);
pipeId++;
task1.on('exit', launch);
};
launch();
UPDATE3:這更好地說明了我的問題。我試圖在原始代碼中簡化它,但我認爲它太簡化了。拉里Turtis提供了簡化的情況的方法,但並不適用於礦山:
var spawn = require('child_process').spawn;
var pipeId = 0;
var pipeSlots = 6;
var launchProcess = function(cmd, args, stdin, stdout){
return spawn(cmd, args, {
stdio: [stdin, stdout, 'ignore']
});
};
var launch = function(){
var task0 = launchProcess('echo', ['how\nare\nyou\ndear\nstranger'], 'ignore', 'pipe');
var task1 = launchProcess('tee', ['/tmp/body-pipeline-' + pipeId], task0.stdout, 'ignore');
task0.on('error', function(err){
console.log('Error while processing task0:' + err.stack);
});
task1.on('error', function(err){
console.log('Error while processing task1:' + err.stack);
});
pipeId++;
};
// Simulating message queue
setInterval(function(){
// Simulating how many messages we get from the messaging queue
var mqMessageCount = Math.floor(Math.random() * (pipeSlots + 1));
for(var i = 0; i < mqMessageCount; i++){
launch();
}
}, 250); // For this test we assume that pipes finish under 250ms
提示:您應該幾乎總是使用子進程的'close'事件而不是'exit',因爲前者表示stdout/stderr上不會有更多數據可用。 ''close''總是在'exit'後出現。 – mscdex
@mscdex謝謝你的信息!根據其他spawn進程是否正在運行或完成,產生新進程不應具有不同的行爲。 –