javascript Node.js child_process exec 的标准输出被缩短

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21188815/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 20:19:24  来源:igfitidea点击:

Stdout of Node.js child_process exec is cut short

javascriptnode.jsexecstdoutchild-process

提问by Alex H Hadik

In Node.js I'm using the exec command of the child_process module to call an algorithm in Java that returns a large amount of text to standard out which I then parse and use. I'm able to capture it mostly, but when it exceeds a certain number of lines, the content is cutoff.

在 Node.js 中,我使用 child_process 模块的 exec 命令调用 Java 中的算法,该算法将大量文本返回到标准输出,然后我解析和使用这些文本。我大部分都能捕捉到它,但是当它超过一定数量的行时,内容就会被截断。

exec("sh target/bin/solver "+fields.dimx+" "+fields.dimy, function(error, stdout, stderr){
    //do stuff with stdout
}

I've tried using setTimeouts and callbacks but haven't succeeded but I do feel this is occurring because I'm referencing stdout in my code before it can be retrieved completely. I have tested that stdout is in-fact where the data loss first occurs. It's not an asynchronous issue further down the line. I've also tested this on my local machine and Heroku, and the exact same issue occurs, truncating at the exact same line number every time.

我试过使用 setTimeouts 和回调,但没有成功,但我确实觉得这正在发生,因为我在我的代码中引用了标准输出,然后才能完全检索它。我已经测试过标准输出实际上是首先发生数据丢失的地方。这不是更深入的异步问题。我也在我的本地机器和 Heroku 上对此进行了测试,并且发生了完全相同的问题,每次都在完全相同的行号处截断。

Any ideas or suggestions as to what might help with this?

关于什么可能有帮助的任何想法或建议?

采纳答案by damphat

Edited: I have tried with dir /son my computer (windows) and got the same problem( it look like a bug), this code solve that problem for me:

编辑:我dir /s在我的电脑 ( windows)上尝试过并遇到了同样的问题(它看起来像一个错误),这段代码为我解决了这个问题:

var exec = require('child_process').exec;

function my_exec(command, callback) {
    var proc = exec(command);

    var list = [];
    proc.stdout.setEncoding('utf8');

    proc.stdout.on('data', function (chunk) {
        list.push(chunk);
    });

    proc.stdout.on('end', function () {
        callback(list.join());
    });
}

my_exec('dir /s', function (stdout) {
    console.log(stdout);
})

回答by olamotte

I had exec.stdout.on('end') callbacks hung forever with @damphat solution.

我有 exec.stdout.on('end') 回调永远挂起@damphat 解决方案。

Another solution is to increase the buffer size in the options of exec: see the documentation here

另一种解决方案是在 exec 的选项中增加缓冲区大小:请参阅此处的文档

{ encoding: 'utf8',
  timeout: 0,
  maxBuffer: 200*1024, //increase here
  killSignal: 'SIGTERM',
  cwd: null,
  env: null }

To quote: maxBuffer specifies the largest amount of data allowed on stdout or stderr - if this value is exceeded then the child process is killed. I now use the following: this does not require handling the separated parts of the chunks separated by commas in stdout, as opposed to the accepted solution.

引用: maxBuffer 指定 stdout 或 stderr 上允许的最大数据量 - 如果超过此值,则子进程将被终止。我现在使用以下内容:与接受的解决方案相反,这不需要处理在标准输出中用逗号分隔的块的分隔部分。

exec('dir /b /O-D ^2014*', {
    maxBuffer: 2000 * 1024 //quick fix
    }, function(error, stdout, stderr) {
        list_of_filenames = stdout.split('\r\n'); //adapt to your line ending char
        console.log("Found %s files in the replay folder", list_of_filenames.length)
    }
);

回答by igelineau

The real (and best) solution to this problem is to use spawn instead of exec. As stated in this article, spawn is more suited for handling large volumes of data :

这个问题的真正(也是最好的)解决方案是使用 spawn 而不是 exec。如本文所述, spawn 更适合处理大量数据:

child_process.exec returns the whole buffer output from the child process. By default the buffer size is set at 200k. If the child process returns anything more than that, you program will crash with the error message "Error: maxBuffer exceeded". You can fix that problem by setting a bigger buffer size in the exec options. But you should not do it because exec is not meant for processes that return HUGE buffers to Node. You should use spawn for that. So what do you use exec for? Use it to run programs that return result statuses, instead of data.

child_process.exec 返回子进程的整个缓冲区输出。默认情况下,缓冲区大小设置为 200k。如果子进程返回的内容不止于此,您的程序将因错误消息“错误:超出 maxBuffer”而崩溃。您可以通过在 exec 选项中设置更大的缓冲区大小来解决该问题。但是您不应该这样做,因为 exec 不适用于将巨大缓冲区返回给 Node 的进程。您应该为此使用 spawn。那么你用 exec 做什么?使用它来运行返回结果状态而不是数据的程序。

spawn requires a different syntax than exec :

spawn 需要与 exec 不同的语法:

var proc = spawn('sh', ['target/bin/solver', 'fields.dimx', 'fields.dimy']);

proc.on("exit", function(exitCode) {
    console.log('process exited with code ' + exitCode);
});

proc.stdout.on("data", function(chunk) {
    console.log('received chunk ' + chunk);
});

proc.stdout.on("end", function() {
    console.log("finished collecting data chunks from stdout");
});