次のCプログラム(test.c)について考えてみます。
#include <stdio.h>
int main() {
printf("string out 1\n");
fprintf(stderr, "string err 1\n");
getchar();
printf("string out 2\n");
fprintf(stderr, "string err 2\n");
fclose(stdout);
}
これは、行をstdoutに、行をstderrに出力し、ユーザー入力を待ってから、別の行をstdoutに、別の行をstderrに出力する必要があります。とても基本的です!コンパイルしてコマンドラインで実行すると、プログラムの出力が完了します(getchar()のユーザー入力を受け取ります)。
$ ./test
string out 1
string err 1
string out 2
string err 2
次のコードでnodejsを使用して、このプログラムを子プロセスとして生成しようとした場合:
var TEST_EXEC = './test';
var spawn = require('child_process').spawn;
var test = spawn(TEST_EXEC);
test.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
test.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
// Simulate entering data for getchar() after 1 second
setTimeout(function() {
test.stdin.write('\n');
}, 1000);
出力は次のようになります。
$ nodejs test.js
stderr: string err 1
stdout: string out 1
string out 2
stderr: string err 2
ターミナルで./testを実行したときに見られる出力とは大きく異なります。これは、nodejsによって生成されたときに./testプログラムがインタラクティブシェルで実行されていないためです。test.c stdoutストリームはバッファリングされ、\ nに到達するとすぐにターミナルで実行されるとバッファがフラッシュされますが、ノードでこの方法で生成された場合、バッファはフラッシュされません。これは、印刷のたびにstdoutをフラッシュするか、stdoutストリームをバッファなしに変更して、すべてをすぐにフラッシュすることで解決できます。test.cソースが利用できない、または変更できないと仮定すると、前述の2つのフラッシュオプションのどちらも実装できません。
次に、インタラクティブシェルのエミュレートを検討し始めました。たとえば、次のように、適切に機能するpty.js(疑似端末)があります。
var spawn = require('pty.js').spawn;
var test = spawn(TEST_EXEC);
test.on('data', function (data) {
console.log('data: ' + data);
});
// Simulate entering data for getchar() after 1 second
setTimeout(function() {
test.write('\n');
}, 1000);
どの出力:
$ nodejs test.js
data: string out 1
string err 1
data:
data: string out 2
string err 2
ただし、stdoutとstderrの両方がマージされ(ターミナルでプログラムを実行しているときにわかるように)、ストリームからデータを分離する方法を考えることはできません。
だから質問..
test.cコードを変更せずに./testを実行したときに見られるような出力を達成するためにnodejsを使用する方法はありますか?ターミナルエミュレーションまたはプロセススポーンまたはその他の方法のいずれかによって?
乾杯!