Stdout из Node.js child_process exec прерван
В Node.js Я использую команду exec модуля child_process для вызова алгоритма в Java, который возвращает большое количество текста в стандартную версию, из которой я тогда разбираюсь и использую. Я могу захватить его в основном, но когда он превышает определенное количество строк, содержимое отключается.
exec("sh target/bin/solver "+fields.dimx+" "+fields.dimy, function(error, stdout, stderr){
//do stuff with stdout
}
Я пробовал использовать setTimeouts и обратные вызовы, но не удалось, но я чувствую, что это происходит, потому что я ссылаюсь на stdout в своем коде, прежде чем он может быть полностью восстановлен. Я тестировал, что stdout на самом деле происходит с потерей данных. Это не асинхронная проблема дальше по линии. Я также тестировал это на своей локальной машине и Heroku, и такая же проблема возникает, каждый раз обрезая один и тот же номер строки.
Любые идеи или предложения относительно того, что может помочь с этим?
Ответы
Ответ 1
Отредактировано:
Я попытался с dir /s
на моем компьютере (windows
) и получил ту же проблему (это похоже на ошибку), этот код решает эту проблему для меня:
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);
})
Ответ 2
У меня были exec.stdout.on('end') обратные вызовы, навешенные навсегда с помощью решения @damphat.
Другим решением является увеличение размера буфера в параметрах exec: см. документацию здесь
{ 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)
}
);
Ответ 3
Реальное (и лучшее) решение этой проблемы заключается в использовании spawn вместо exec.
Как указано в этой статье, 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");
});