Problema de buffer padrão usando nó child_process

91

Estou tentando executar o curl usando o nó child_process para obter um arquivo JSON (cerca de 220Ko) de uma pasta compartilhada em uma rede local. Mas na verdade retorna um problema de buffer que não consigo resolver. Aqui está o meu código:

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

E aqui está o erro que recebo:

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)
Yonnaled
fonte

Respostas:

161

Você precisa usar e definir a maxBufferopção ao usar child_process.exec. Da documentação :

maxBuffer especifica a maior quantidade de dados permitida em stdout ou stderr - se esse valor for excedido, o processo filho será eliminado.

A documentação também afirma que o valor padrão de maxBufferé 200 KB.

Por exemplo, o tamanho máximo do buffer é aumentado para 500 KB no seguinte código:

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

Além disso, você pode querer ler sobre http.getpara ver se ele é capaz de realizar o que você está tentando fazer.

Tim Cooper
fonte
Isso resolveu meu problema, obrigado! A pasta compartilhada está na verdade sob o protocolo webdav que requer uma autenticação digest, é por isso que estou usando curl, que lida com isso muito facilmente comcurl --digest http://login:password@" + ip + "/webdav/file.json
Yonnaled
Esse padrão é ridiculamente pequeno. Esta é a segunda vez que fui mordido por isso de uma forma difícil de encontrar.
jlh
3
O padrão agora é 1 MB @jlh, nodejs.org/api/…
Carlos
57

Eu tive um problema semelhante e corrigi-lo ao passar de executivo para 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);
});
Isampaio
fonte
10
Esta parece ser a solução mais apropriada das duas
Hashbrown
1
Essa resposta não é necessariamente a mais adequada. Acho que a saída do console em questão poderia ser apenas um exemplo. Dificilmente alguém iria buscar um arquivo de 200 KB para jogá-lo no console. No entanto, se process.execfor usado em coisas como ferramentas CLI, então sim, mudar para spawndeve ser o caminho a percorrer.
Pavel Gatilov
1
uau ... desova é legal. Não está nem usando callbacks ou promessas ... apenas eventos. Isso pode ser realmente útil para transmitir stdout para o console. @Pavel Gatilov, é exatamente o que estamos fazendo. FFMpeg gosta de mostrar o progresso a cada segundo ... o que afeta o buffer
Ray Foss