节点 Kue 和子进程 - 从生成的进程中获取错误

Posted

技术标签:

【中文标题】节点 Kue 和子进程 - 从生成的进程中获取错误【英文标题】:Node Kue and Child Process - get error from spawned process 【发布时间】: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 中的错误/失败消息。你有什么推荐的? 【参考方案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(),它希望成为失败事件的“解释”/“错误追溯”的一部分,只是一个正常的日志事件..?我怎样才能缓冲它?

以上是关于节点 Kue 和子进程 - 从生成的进程中获取错误的主要内容,如果未能解决你的问题,请参考以下文章

节点工作进程 / cron 工作建议

Python多处理和子进程的独立性

使用管道在父进程和子进程之间进行通信的问题

什么是父进程和子进程?

swoole父进程和子进程之间通信的例子

swoole父进程和子进程之间通信的例子