【问题标题】:Node Kue and Child Process - get error from spawned process节点 Kue 和子进程 - 从生成的进程中获取错误
【发布时间】:2014-08-17 00:25:30
【问题描述】:

我尝试使用 Kue 通过作业队列生成一个执行 cpu 密集型计算的子进程。我目前的代码如下所示:

consumer.js

var kue = require('kue');
var util  = require('util');
var spawn = require('child_process').spawn;

var jobs = kue.createQueue();

jobs.process('calc', 2, function(job, done){
  var work = spawn('Rscript', ['opti2.R', job.data.file]);

  work.stderr.on('data', function (data) {
    job.log('stderr: ' + data);
  });

  work.stdout.on('data', function (data) {
    job.log('stdout: ' + data);
  });

  work.on('exit', function (code, signal) {
    console.log('child process exited with code ' + code + ' with singal ' + signal);
    if(code != 0){
      done(****How to get the stderr of the child process as an error here***);
    } else {
      done(Error());
    }
  });
});

代码在某种程度上做了我想做的事,但是有没有更好的方法来报告作业失败(向 Kue)并从生成的进程中获取标准错误?

【问题讨论】:

  • 您希望将孩子的stdio 传送到父母的stdio,还是将其发送到Kue
  • @LeonidBeschastny:不确定(对节点/编程来说非常新),但希望将生成过程中的错误作为 Kue 中的错误/失败消息。你有什么推荐的?

标签: node.js child-process kue


【解决方案1】:

您可以使用job.log method直接向Kue发送数据。

我还建议您从.spawn 切换到.exec,因为它在最终回调中返回stdoutstderr 作为字符串以及一个很好的error,这很适合您的需求:

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

jobs.process('calc', 2, function(job, done){
  exec('Rscript opti2.R ' + job.data.file, function (error, stdout, stderr) {
    if (stdout.length > 0) job.log('stdout: ' + stdout);
    if (stderr.length > 0) job.log('stderr: ' + stderr);
    done(error);
  });
});

虽然解决方案也适用于 .spawn:只需将代码中的每个 console.log 调用替换为 job.log

不过,您可能希望缓冲您的 stderr 以便将其分成一个块发送给 Kue:

jobs.process('calc', 2, function(job, done){
  var work = spawn('Rscript', ['opti2.R', job.data.file]);
  var stderr = '';

  work.stderr.on('data', function (data) {
    stderr += data;
  });

  work.stdout.on('data', function (data) {
    job.log(data); // sending arriving `stdout` chunks as normal log events
  });

  work.on('close', function (code, signal) {
    console.log('child process exited with code ' + code + ' with singal ' + signal);
    if(code != 0){
      done(stderr); // sending all collected stderr as an explanation
    } else {
      done();
    }
  });
});

我还建议使用close 事件而不是exit,因为它等待孩子的stdio 流。

更多信息见Event: 'exit' docs:

该事件在子进程结束后触发。

请注意,子进程 stdio 流可能仍处于打开状态。

Event: 'close' docs:

当子进程的 stdio 流有 全部终止。

【讨论】:

  • 计算运行 30-90 分钟并输出(标准输出),我想返回网页,因此我使用 spawn。有没有办法将错误从 stderr 事件传递到 Kue 的 done() ?
  • @JamesBund 正如我所说,此解决方案也适用于.spawn,只需使用job.log 将数据发送到Kue,而不是将其记录到控制台。
  • 不确定是否误解了某些东西,但是使用 job.log 我仍然无法在孩子的退出事件中使用来自孩子的 stderr 作为 done() 的参数?已更新代码..
  • @JamesBund 在.on 'exit' 回调中获得完整的stderr 的唯一方法是手动缓冲它。不过,您编辑的代码应该允许您在 Kue 中看到孩子的 stderr,而无需将其传递给 done() 回调。
  • 但如果我不将它传递给 done(),它希望成为失败事件的“解释”/“错误追溯”的一部分,只是一个正常的日志事件..?我怎样才能缓冲它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 2020-10-18
相关资源
最近更新 更多