Problema del buffer stdout utilizzando il nodo child_process


91

Sto cercando di eseguire curl utilizzando il nodo child_process per ottenere un file JSON (circa 220Ko) da una cartella condivisa in una rete locale. Ma in realtà restituisce un problema di buffer che non riesco a risolvere. Ecco il mio codice:

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

Ed ecco l'errore che ottengo:

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)

Risposte:


161

È necessario utilizzare e impostare l' maxBufferopzione durante l'utilizzo child_process.exec. Dalla documentazione :

maxBuffer specifica la quantità massima di dati consentita su stdout o stderr - se questo valore viene superato, il processo figlio viene interrotto.

La documentazione afferma inoltre che il valore predefinito di maxBufferè 200 KB.

Ad esempio, la dimensione massima del buffer viene aumentata a 500 KB nel codice seguente:

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

Inoltre, potresti voler leggere http.getper vedere se è in grado di ottenere ciò che stai cercando di fare.


Questo ha risolto il mio problema, grazie! La cartella condivisa è in realtà sotto il protocollo webdav che richiede un'autenticazione digest, ecco perché sto usando curl che la gestisce molto facilmente concurl --digest http://login:password@" + ip + "/webdav/file.json
Yonnaled

Questa impostazione predefinita è ridicolmente piccola. Questa è la seconda volta che sono stato morso da questo in un modo difficile da trovare.
jlh

3
L'impostazione predefinita è ora 1 MB @jlh, nodejs.org/api/…
Carlos

57

Ho avuto un problema simile e l'ho risolto passando da exec a 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
Questa sembra essere la soluzione più appropriata delle due
Hashbrown

1
Questa risposta non è necessariamente la più appropriata. Penso che l'output della console nella domanda potrebbe essere solo un esempio. Difficilmente qualcuno recupererebbe un file da 200 KB per lanciarlo sulla console. Tuttavia, se process.execviene utilizzato in cose come gli strumenti CLI, allora sì, il passaggio a spawndovrebbe essere la strada da percorrere.
Pavel Gatilov

1
wow ... spawn è fantastico. Non sta nemmeno usando call back o promesse ... solo eventi. Potrebbe essere davvero utile per lo streaming di stdout sulla console. @Pavel Gatilov, è esattamente quello che stiamo facendo. FFMpeg ama mostrare i progressi ogni secondo ... il che richiede un pedaggio sul buffer
Ray Foss
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.