Проблема с буфером стандартного вывода с использованием узла child_process

92

Я пытаюсь выполнить curl с помощью узла child_process, чтобы получить файл JSON (около 220Ko) из общей папки в локальной сети. Но на самом деле он возвращает проблему с буфером, с которой я не могу справиться. Вот мой код:

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

var execute = function(command, callback){
    exec(command, function(error, stdout, stderr){ callback(error, stdout); });
};

execute("curl http://" + ip + "/file.json", function(err, json, outerr) {
    if(err) throw err;
    console.log(json);
})

И вот ошибка, которую я получаю:

if(err) throw err;
          ^
Error: stdout maxBuffer exceeded.
    at Socket.<anonymous> (child_process.js:678:13)
    at Socket.EventEmitter.emit (events.js:95:17)
    at Socket.<anonymous> (_stream_readable.js:746:14)
    at Socket.EventEmitter.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:408:10)
    at emitReadable (_stream_readable.js:404:5)
    at readableAddChunk (_stream_readable.js:165:9)
    at Socket.Readable.push (_stream_readable.js:127:10)
    at Pipe.onread (net.js:526:21)
Йонналед
источник

Ответы:

161

Вам нужно использовать и установить maxBufferопцию при использовании child_process.exec. Из документации :

maxBuffer указывает самый большой объем данных, разрешенный для stdout или stderr - если это значение превышено, дочерний процесс уничтожается.

В документации также указано, что значение по умолчанию maxBuffer- 200 КБ.

Например, максимальный размер буфера увеличивается до 500 КБ в следующем коде:

var execute = function(command, callback){
    exec(command, {maxBuffer: 1024 * 500}, function(error, stdout, stderr){ callback(error, stdout); });
};

Кроме того, вы можете прочитать о http.getтом, сможет ли он достичь того, что вы пытаетесь сделать.

Тим Купер
источник
Это решило мою проблему, спасибо! Общая папка на самом деле находится под протоколом webdav, который требует дайджест-аутентификации, поэтому я использую curl, который очень легко справляется с этимcurl --digest http://login:password@" + ip + "/webdav/file.json
Йонналед
Это значение по умолчанию смехотворно мало. Это второй раз, когда меня это укусило, и это было трудно найти.
jlh
3
По умолчанию теперь 1 МБ @jlh, nodejs.org/api/…
Карлос
57

У меня была аналогичная проблема, и я исправил ее при переходе от exec к spawn:

var child = process.spawn('<process>', [<arg1>, <arg2>]);

child.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

child.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

child.on('close', function (code) {
    console.log('child process exited with code ' + code);
});
Исампайо
источник
10
Это кажется наиболее подходящим решением из двух
Hashbrown
1
Этот ответ не обязательно самый подходящий. Я думаю, что вывод консоли в вопросе может быть просто примером. Вряд ли кто-то сможет скачать файл размером 200 КБ, чтобы выкинуть его на консоль. Однако, если process.execон используется в таких вещах, как инструменты CLI, то да, переход на него spawnдолжен быть правильным решением.
Павел Гатилов
1
вау ... спаун это круто. Он даже не использует обратные вызовы или обещания ... просто события. Это может быть действительно полезно для потоковой передачи стандартного вывода на консоль. @ Павел Гатилов, это именно то, что мы делаем. FFMpeg любит показывать прогресс каждую секунду ... что сказывается на буфере,
Рэй Фосс,