没有从 nodejs 生成的进程接收标准输出
Not receiving stdout from nodejs spawned process
我正在尝试让 nodejs 与 adventure 交互,这是一个基于文本的旧游戏。这个想法是将冒险作为子进程打开,然后通过写入其 stdin
并在 stdout
上放置事件侦听器来玩游戏。
当游戏开始时,它会打印一个首字母:
Welcome to Adventure!! Would you like instructions?
为了说明我的问题,我有一个 nodejs+express 实例:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
但是当我启动服务器时,游戏中的文本没有到达事件侦听器:
spawned: 24250
这就是我得到的所有输出。 child.stdout.on
even 侦听器永远不会被调用。为什么没有提取游戏的初始台词?
如果我将以下行附加到上面的 javascript 块,那么程序输出会立即出现。所以 adventure
运行,我现在可以强制它触发 child.stdout.on
事件侦听器......但这也结束了子进程,这违背了读写它的目的。
...
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
child.stdin.end();
现在输出是:
spawned: 28778
Child data:
Welcome to Adventure!! Would you like instructions?
user closed input stream, quitting...
Finished collecting data chunks.
Child process exited with code 0
我确信这是我的一个微不足道的疏忽,但我很感激任何帮助解决这个问题的人。
传递的data
是缓冲区类型,不是字符串。因此,您需要一个解码器来读取该缓冲区,然后进行日志记录。
这是如何做到这一点。
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
child.stdout.on('data', function (data) {
var message = decoder.write(data);
console.log(message.trim());
});
在多次浏览 Nodejs 文档之后,我确信自己要么遗漏了一些非常重要的东西,要么 spawn
命令无法正常工作。所以我创建了一个 github issue.
答案马上贴出来了:如果你想快速访问,子进程不能缓冲输出。
所以为了实现我最初寻找的目标:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('unbuffer', 'adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
功能差异在于使用 unbuffer
,一个禁用输出缓冲的命令。
Why isn't that initial line from the game being picked up?
我在一个从 node.js 调用已编译 C++ 程序的项目中遇到了同样的问题。我意识到问题出在编译的 C++ 程序中:我没有刷新 stdout
流。在打印一行后添加 fflush(stdout);
解决了这个问题。希望您仍然可以访问游戏源!
我正在尝试让 nodejs 与 adventure 交互,这是一个基于文本的旧游戏。这个想法是将冒险作为子进程打开,然后通过写入其 stdin
并在 stdout
上放置事件侦听器来玩游戏。
当游戏开始时,它会打印一个首字母:
Welcome to Adventure!! Would you like instructions?
为了说明我的问题,我有一个 nodejs+express 实例:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
但是当我启动服务器时,游戏中的文本没有到达事件侦听器:
spawned: 24250
这就是我得到的所有输出。 child.stdout.on
even 侦听器永远不会被调用。为什么没有提取游戏的初始台词?
如果我将以下行附加到上面的 javascript 块,那么程序输出会立即出现。所以 adventure
运行,我现在可以强制它触发 child.stdout.on
事件侦听器......但这也结束了子进程,这违背了读写它的目的。
...
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
child.stdin.end();
现在输出是:
spawned: 28778
Child data:
Welcome to Adventure!! Would you like instructions?
user closed input stream, quitting...
Finished collecting data chunks.
Child process exited with code 0
我确信这是我的一个微不足道的疏忽,但我很感激任何帮助解决这个问题的人。
传递的data
是缓冲区类型,不是字符串。因此,您需要一个解码器来读取该缓冲区,然后进行日志记录。
这是如何做到这一点。
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
child.stdout.on('data', function (data) {
var message = decoder.write(data);
console.log(message.trim());
});
在多次浏览 Nodejs 文档之后,我确信自己要么遗漏了一些非常重要的东西,要么 spawn
命令无法正常工作。所以我创建了一个 github issue.
答案马上贴出来了:如果你想快速访问,子进程不能缓冲输出。
所以为了实现我最初寻找的目标:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var child = spawn('unbuffer', 'adventure');
console.log("spawned: " + child.pid);
child.stdout.on('data', function(data) {
console.log("Child data: " + data);
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
功能差异在于使用 unbuffer
,一个禁用输出缓冲的命令。
Why isn't that initial line from the game being picked up?
我在一个从 node.js 调用已编译 C++ 程序的项目中遇到了同样的问题。我意识到问题出在编译的 C++ 程序中:我没有刷新 stdout
流。在打印一行后添加 fflush(stdout);
解决了这个问题。希望您仍然可以访问游戏源!