Node.js的交互生成一个子进程有独立的输出和错误流(Node.js spawning a chi

2019-07-21 08:35发布

考虑下面的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和另一条线路标准错误。 非常基本的! 当编译并在命令行上运行该程序的输出时(被接收的用户输入对的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程序没有在交互shell中运行。 有test1.c标准输出流被缓冲并且在终端中,一旦一个\ n为达到缓冲器运行时被刷新但以这种方式与节点催生当缓冲器是不刷新。 这可以通过两种冲洗标准输出每次打印后加以解决,或者改变标准输出流,因此会立即刷新一切是无缓冲。 假设test.c的源不可用或修改,都不提到的两个冲洗选项可以被实现。

然后我就开始寻找模拟交互的shell,有它做得很好,例如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和标准错误被合并在一起,我不能想办法把数据从流分开(如你在终端运行时程序见)。

所以,问题..

有没有使用到的NodeJS实现输出,而无需修改代码test.c的运行./test时所看到的任何方式? 或者通过终端仿真或过程产卵或任何其他方法?

干杯!

Answer 1:

我想,答案由user568109但这不起作用,这是有道理的,因为管道仅复制流之间的数据。 因此,只到达process.stdout当缓冲区被刷新......下面似乎工作:

var TEST_EXEC = './test';

var spawn = require('child_process').spawn;
var test = spawn(TEST_EXEC, [], { stdio: 'inherit' });

//the following is unfortunately not working 
//test.stdout.on('data', function (data) {
//  console.log('stdout: ' + data);
//});

请注意,这有效地共享标准输入输出与节点的过程。 不知道,如果你可以忍受的。



Answer 2:

我只是重温这一点,因为现在有可用的,因为5.7.0版本在节点产卵命令“shell”选项。 不幸的是,似乎没有要产卵的交互式 shell的选项(我也试图与shell: '/bin/sh -i' ,但没有喜悦)。 不过,我刚刚发现这个提示使用“stdbuf”让你改变你想要运行的程序的缓存选项。 将它们设置为0的一切产生的所有流缓冲输出和他们仍然保持独立。

下面是更新后的javascript:

var TEST_EXEC = './test';

var spawn = require('child_process').spawn;
var test = spawn('stdbuf', ['-i0', '-o0', '-e0', 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);

看起来这是不是在OSX,当然不适用于Windows的预装,可以是类似的替代品,但。



Answer 3:

你可以这样做 :

var TEST_EXEC = 'test';
var spawn = require('child_process').spawn;
var test = spawn(TEST_EXEC);

test.stdin.pipe(process.stdin);
test.stdout.pipe(process.stdout);
test.stderr.pipe(process.stderr);

当您使用事件stdoutstderr上打印输出console.log ,您将获得因为函数的异步执行的混乱输出。 输出将被单独订购流,但产量仍可以获得之间交错的stdinstdoutstderr



文章来源: Node.js spawning a child process interactively with separate stdout and stderr streams