node.js gerando um processo filho interativamente com streams stdout e stderr separados

Considere o seguinte programa 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);
}

Qual deve imprimir uma linha para stdout, uma linha para stderr, então espere pela entrada do usuário, então outra linha para stdout e outra linha para stderr. Muito básico! Quando compilado e executado na linha de comando, a saída do programa é concluída (a entrada do usuário é recebida para getchar ()):

$ ./test 
string out 1
string err 1

string out 2
string err 2

Ao tentar gerar este programa como um processo filho usando o nodejs com o seguinte código:

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);

A saída aparece assim:

$ nodejs test.js 
stderr: string err 1

stdout: string out 1
string out 2

stderr: string err 2

Muito diferente da saída como visto ao executar ./test no terminal. Isso ocorre porque o programa ./test não está sendo executado em um shell interativo quando gerado por nodejs. O fluxo stdout test.c é armazenado em buffer e quando executado em um terminal assim que um \ n é atingido, o buffer é liberado, mas quando gerado dessa maneira com o nó, o buffer não é liberado. Isso pode ser resolvido pela descarga da stdout após cada impressão ou pela alteração do fluxo de stdout para que ele fique sem buffer, liberando tudo imediatamente. Assumindo que a fonte test.c não está disponível ou modificável, nenhuma das duas opções mencionadas pode ser implementada.

Comecei então a analisar a emulação de um shell interativo, há o pty.js (pseudo terminal) que faz um bom trabalho, por exemplo:

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);

Quais saídas:

$ nodejs test.js
data: string out 1
string err 1

data: 

data: string out 2
string err 2

No entanto, ambos stdout e stderr são mesclados juntos (como você veria ao executar o programa em um terminal) e não consigo pensar em uma maneira de separar os dados dos fluxos.

Então a questão ..

Existe alguma maneira de usar o nodejs para obter a saída como visto ao executar o ./test sem modificar o código do test.c? Por emulação de terminal ou desova de processo ou qualquer outro método?

Felicidades!

questionAnswers(3)

yourAnswerToTheQuestion