简体   繁体   English

没有从nodejs生成的进程接收stdout

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM