[英]Not receiving stdout from nodejs spawned process
I'm trying to have nodejs interact with adventure , an old text based game. 我正在尝试让nodejs与冒险 ,一个旧的基于文本的游戏进行交互。 The idea is to open adventure as a child process and then play the game by writing to its stdin
and placing an event listener on stdout
. 这个想法是将冒险作为一个子进程开放,然后通过写入stdin
并在stdout
上放置一个事件监听器来玩游戏。
When the game starts, it prints an initial: 游戏开始时,会打印出一个初始值:
Welcome to Adventure!! 欢迎来到冒险! Would you like instructions? 你想要指示吗?
So to illustrate my problem, I have a nodejs+express instance with: 所以为了说明我的问题,我有一个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.');
});
But when I start the server, the text from the game doesn't reach the event listener: 但是当我启动服务器时,游戏中的文本没有到达事件监听器:
spawned: 24250
That's all the output I get. 这就是我得到的所有输出。 The child.stdout.on
even listener is never called. 永远不会调用child.stdout.on
甚至是监听器。 Why isn't that initial line from the game being picked up? 为什么游戏中的初始线不会被拾取?
If I append the following line to the above block of javascript, then the program output appears at once. 如果我将以下行附加到上面的javascript块,则程序输出立即出现。 So adventure
runs, and I can now force it to trigger the child.stdout.on
event listener... but this also ends the child process, which defeats the purpose of reading and writing to it. 所以adventure
运行,我现在可以强制它触发child.stdout.on
事件监听器...但这也结束了子进程,这违背了读写它的目的。
...
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
child.stdin.end();
Now the output is: 现在的输出是:
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
I'm sure its a trivial oversight on my part, I appreciate any help figuring this out though. 我确信这对我来说是一个微不足道的疏忽,我感谢任何有助于解决这个问题的人。
After going through the Nodejs documentation a few more times, I convinced myself I was either missing something pretty big, or the spawn
command wasn't working correctly. 经过Nodejs文档几次之后,我确信自己错过了一些非常大的东西,或者spawn
命令无法正常工作。 So I created a github issue . 所以我创建了一个github问题 。
And the answer was immediately posted: the child process can't buffer output if you want fast access. 答案立即发布:如果您想快速访问,子进程无法缓冲输出。
So to achieve what I was originally looking for: 所以要实现我最初寻找的东西:
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.');
});
With the functional difference being the use of unbuffer
, a command that disables output buffering. 功能差异在于使用unbuffer
,这是一个禁用输出缓冲的命令。
Why isn't that initial line from the game being picked up? 为什么游戏中的初始线不会被拾取?
I had the same problem on a project that called a compiled C++ program from node.js. 我在从node.js调用编译的C ++程序的项目上遇到了同样的问题。 I realized the problem was in the compiled C++ program: I wasn't flushing the stdout
stream. 我意识到问题出在编译的C ++程序中:我没有刷新stdout
流。 Adding fflush(stdout);
添加fflush(stdout);
after printing a line solved the issue. 印刷线后解决了问题。 Hopefully you still have access to the source of the game! 希望你仍然可以访问游戏的来源!
The data
passed is a buffer type, not a string. 传递的data
是缓冲区类型,而不是字符串。 Therefore, you need a decoder to read that buffer and then do the logging. 因此,您需要一个解码器来读取该缓冲区,然后进行日志记录。
Here's how to do that. 这是怎么做的。
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());
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.