Node.js的stdout child_process exec被缩短了

时间:2014-01-17 14:54:20

标签: javascript node.js exec stdout child-process

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

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

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

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

3 个答案:

答案 0 :(得分:10)

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

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

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

引用: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)
    }
);

答案 1 :(得分:8)

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

  

child_process.exec返回子进程的整个缓冲区输出。默认情况下,缓冲区大小设置为200k。如果子进程返回的内容不止于此,则程序将崩溃并显示错误消息"错误:超出maxBuffer"。您可以通过在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");
});

答案 2 :(得分:4)

编辑: 我在我的计算机上尝试dir /swindows)并遇到了同样的问题(看起来像个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);
})