node.js interaktywnie uruchamia proces potomny z oddzielnymi strumieniami stdout i stderr

Rozważmy następujący program 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);
}

Które powinny wypisać linię na stdout, linię na stderr, następnie poczekać na wprowadzenie danych przez użytkownika, następnie kolejną linię na stdout i inną linię na stderr. Bardzo podstawowy! Po skompilowaniu i uruchomieniu w wierszu poleceń wyjście programu po zakończeniu (dane wejściowe użytkownika są odbierane dla getchar ()):

$ ./test 
string out 1
string err 1

string out 2
string err 2

Podczas próby zrobienia tego programu jako procesu potomnego za pomocą nodejs z następującym kodem:

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

Wynik wygląda następująco:

$ nodejs test.js 
stderr: string err 1

stdout: string out 1
string out 2

stderr: string err 2

Bardzo różni się od wyjścia widocznego podczas uruchamiania ./testu w terminalu. Dzieje się tak, ponieważ program ./test nie działa w interaktywnej powłoce, gdy jest uruchamiany przez nodejs. Strumień stdout test.c jest buforowany, a po uruchomieniu w terminalu, gdy tylko n zostanie osiągnięty, bufor jest opróżniany, ale gdy pojawi się w ten sposób z węzłem, bufor nie jest opróżniany. Można to rozwiązać przez opróżnienie stdout po każdym wydruku lub zmianę strumienia stdout na niebuforowany, aby natychmiast spłukał wszystko. Zakładając, że źródło test.c nie jest dostępne lub można go modyfikować, żadna z dwóch wymienionych opcji opróżniania nie może zostać zaimplementowana.

Potem zacząłem przyglądać się emulacji powłoki interaktywnej, jest pty.js (pseudo-terminal), który wykonuje dobrą robotę, na przykład:

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

Które wyjścia:

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

data: 

data: string out 2
string err 2

Jednak zarówno stdout, jak i stderr są scalane razem (jak widać podczas uruchamiania programu w terminalu) i nie mogę wymyślić sposobu na oddzielenie danych od strumieni.

Więc pytanie ..

Czy jest jakiś sposób na użycie nodejs do uzyskania wyniku widocznego podczas uruchamiania ./test bez modyfikowania kodu test.c? Albo przez emulację terminala, albo przez spawning procesu, albo przez dowolną inną metodę?

Twoje zdrowie!

questionAnswers(3)

yourAnswerToTheQuestion