Node.js的stdout child_process exec被缩短了

Ale*_*dik 11 javascript stdout exec child-process node.js

在Node.js中,我使用了child_process模块​​的exec命令来调用Java中的算法,该算法将大量文本返回到标准输出,然后我将其解析和使用.我能够捕获它,但是当它超过一定数量的行时,内容就会被截止.

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

我已经尝试过使用setTimeouts和回调但没有成功,但我确实感觉到这种情况正在发生,因为我在我的代码中引用了stdout,然后才能完全检索它.我已经测试过stdout实际上是数据丢失首先发生的地方.这不是一个异步问题.我也在我的本地机器和Heroku上测试了这个,并且出现了完全相同的问题,每次都截断完全相同的行号.

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

ola*_*tte 10

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

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

{ encoding: 'utf8',
  timeout: 0,
  maxBuffer: 200*1024, //increase here
  killSignal: 'SIGTERM',
  cwd: null,
  env: null }
Run Code Online (Sandbox Code Playgroud)

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

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)
    }
);
Run Code Online (Sandbox Code Playgroud)


ige*_*eau 8

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

child_process.exec返回子进程的整个缓冲区输出.默认情况下,缓冲区大小设置为200k.如果子进程返回的内容不止于此,则程序将崩溃,并显示错误消息"Error:maxBuffer exceeded".您可以通过在exec选项中设置更大的缓冲区大小来解决该问题.但是你不应该这样做,因为exec不适用于将HUGE缓冲区返回给Node的进程.你应该使用spawn.那么你用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");
});
Run Code Online (Sandbox Code Playgroud)


dam*_*hat 4

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

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);
})
Run Code Online (Sandbox Code Playgroud)