【问题标题】:Stdout of Node.js child_process exec is cut shortNode.js child_process exec 的标准输出被缩短
【发布时间】:2014-02-06 22:56:04
【问题描述】:

在 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 实际上是第一次发生数据丢失的地方。这不是进一步的异步问题。我也在我的本地机器和 Heroku 上对此进行了测试,并且发生了完全相同的问题,每次都在完全相同的行号处截断。

您有什么想法或建议可以对此有所帮助吗?

【问题讨论】:

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


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的回答!它帮助我了解我的 exec 由于 1MB 的输出而返回错误。不幸的是,exec 的错误对象只返回了命令名称,而没有详细说明错误原因:{"cmd":"./read_mail.sh"}
    【解决方案3】:

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

    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);
    })
    

    【讨论】:

    • 为什么你认为它看起来像一个错误?请看我的回答
    • @olamotte 你可以看到这个答案的历史,我增加了缓冲区大小,但它对我不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 2014-06-19
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多