Узел Kue и дочерний процесс - получить ошибку от порожденного процесса

Я пытаюсь порождать дочерний процесс, выполняющий интенсивные вычисления процессора через очередь заданий с Kue. Мой код на данный момент выглядит так:

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) и получить stderr из порожденного процесса?

1 ответ

Решение

Ты можешь использовать job.log method to send data directly to Kue,

I would also recommend you to switch from .spawn в .exec потому что это возвращает stdout а также stderr as strings in its final callback along with a good error, which suits your needs well:

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

Though solution should work with .spawn as well: simply replace each console.log позвоните в свой код с job.log,

Though, you may want to bufferize your stderr in order to send it to Kue in one chunk:

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, because it waits for child's stdio streams.

Для получения дополнительной информации см. Event: 'exit' документы:

This event is emitted after the child process ends.

Note that the child process stdio streams might still be open.

а также Event: 'close' документы:

This event is emitted when the stdio streams of a child process have all terminated.

Другие вопросы по тегам