子プロセスのstdoutを別のstdinとして使用すると、次の子にデータが渡されないことがあります。子プロセスのstdoutを別の子プロセスのstdoutとして使用すると、2番目の子プロセスにデータが渡されない場合がある
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
にアクセスすることにより、正の整数として、ファイル記述子を渡すと、問題が解決してみました。
私の知る限り、これはシェルパイプの仕組みです。あるプロセスのstdoutと同じファイル記述子が別のプロセスのstdinとして使用されます。子プロセスが大量のデータを出力するときにCPU負荷が高くなるため、NodeJSプロセスですべてのデータを渡すことを避けようとしています。
更新:パイプは、両方の標準入力に使用し、すべてが期待どおりに(長いテキストをテストするために、ここで猫を使用して)動作する標準出力されます。
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();
アップデート2:task0.stdout.pipe(task1.stdin)
を使用している場合、スクリプトは50を使用しています%のCPU(TASK1のSTDINとしてtask0の標準出力を渡すときに0%に比較して):
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は簡略化された場合の回避策を提供したが、それは私のものには適用されません:あなたが終了する2番目のプロセスを待たない場合
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
ヒント:ほとんどの場合、前者はstdout/stderrで利用できるデータがないことを示すので、子プロセスの '' close''イベントを '' exit''の代わりに使用するべきです。 '' close'''は常に '' exit''の後に来ます。 – mscdex
@mscdex情報をありがとうございます!新しいプロセスの起動は、他の起動プロセスが実行中であるか、終了しているかによって異なる動作をすべきではありません。 –