当前位置: 首页 > 面试题库 >

Node.js使用单独的stdout和stderr流以交互方式生成子进程

蓟安歌
2023-03-14
问题内容

考虑下面的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源不可用或不可修改,则提到的两个刷新选项都无法实现。

然后,我开始研究模拟交互式外壳,其中有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都合并在一起了(正如您在终端中运行程序时所看到的),我想不出一种将数据与流分离的方法。

所以问题

有没有什么办法可以使用nodejs在不修改test.c代码的情况下实现./test的输出?是通过终端仿真还是通过进程生成或任何其他方法?

干杯!


问题答案:

我只是在重新讨论一下,因为从5.7.0版开始,节点中的spawn命令现在有了一个’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也不可用,不过可能是类似的选择。



 类似资料:
  • 问题内容: 我想捕获并显示通过Python的子流程调用的流程的输出。 我以为我可以将文件状对象作为参数stdout和stderr传递 我可以看到它访问了属性-因此它正在处理对象。但是,永远不会调用该方法。我的方法是否完全无效或我只是缺少什么? 更新: 我还想工作的是ANSI控制字符,用于移动光标并覆盖以前的输出内容。我不知道这是否是正确的术语,但这是我的意思的一个示例:我正在尝试使一些GIT自动化

  • 问题内容: 我想将子进程的stderr输出重定向到stdout。常量应该这样做,不是吗? 然而, 确实 输出了一些东西。为什么会这样,如何在stdout上得到错误消息? 问题答案: 仔细阅读源代码即可得出答案。特别是,该文档在显示以下内容时会产生误导: 表示(…)的特殊值表示标准错误应与标准输出进入同一 句柄 。 由于在求值时stdout设置为“默认”(技术上来说),因此stderr也设置为“默认

  • 我正在尝试编写一个在后台执行控制台命令并侦听StdOut和StdErr的函数。如果出现错误,它会抛出StdErr和StdOut。我正在尝试使用Autohotkey。首先,我尝试使用WScript。Shell COM Object,但StdErr和StdOut始终为空,尽管StdOut绝对应该为非空。关于WScript的信息不多。Shell COM Object和所有Microsoft文档都在技术档

  • 问题内容: 我正在Python 2.6的GUI前端上工作,通常它非常简单:您使用或发出命令,然后等待命令完成或对错误做出反应。如果您有一个程序停止并等待用户交互,该怎么办?例如,程序可能会停止并要求用户提供ID和密码或如何处理错误? 到目前为止,我所阅读的所有内容都告诉您如何仅 在 程序完成 后 读取程序的所有输出,而不是如何在程序仍在运行时处理输出。我无法安装新模块(这是针对LiveCD的),并

  • [已编辑] 2个选项,用于处理子流程的标准输出。Popen是stdout=“a_file\u name”和stdout=subprocess.PIPE

  • 我正在编写一个库,它应该在子进程中执行一个程序,捕获输出,并以逐行(字符串向量)的方式使输出可用。有一个用于STDOUT的向量,一个用于STDERR,还有一个用于“STDCOMBINED”,即所有输出按程序打印的顺序。子进程通过两个管道连接到父进程。一根用于标准输出,一根用于标准输出。在父进程中,我从管道的读取端读取,在子进程中,我将STDOUT/STDERR插入管道的写入端。 我的问题是:我想捕