【发布时间】:2013-02-26 16:14:01
【问题描述】:
考虑以下 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 时看到的输出非常不同。这是因为 ./test 程序在由 nodejs 生成时没有在交互式 shell 中运行。 test.c 标准输出流被缓冲,当在终端中运行时,一旦到达 \n,缓冲区就会被刷新,但是当使用节点以这种方式产生时,缓冲区不会被刷新。这可以通过在每次打印后刷新 stdout 或将 stdout 流更改为无缓冲以便立即刷新所有内容来解决。 假设 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 和 stderr 都合并在一起(正如您在终端中运行程序时所看到的那样),我想不出一种将数据与流分开的方法。
所以问题..
有没有什么方法可以使用 nodejs 来实现运行 ./test 时看到的输出而不修改 test.c 代码?通过终端仿真或进程生成或任何其他方法?
干杯!
【问题讨论】:
-
感谢您在问题描述中付出了相当大的努力!从节点内运行其他人的 python 脚本时,我遇到了同样的问题,但对底层缓冲机制一无所知。显然(我的 Python 技能 +/- 不存在),只需使用“python -u”即可启用无缓冲 IO 并解决了我的问题!
-
@gratz 你解决了这个问题吗?我面临着类似的问题。你可以从stackoverflow.com/questions/42130677/…
标签: node.js stdout spawn unbuffered