Problème de tampon Stdout avec le nœud child_process

91

J'essaie d'exécuter curl en utilisant le nœud child_process pour obtenir un fichier JSON (environ 220Ko) à partir d'un dossier partagé dans un réseau local. Mais cela renvoie en fait un problème de tampon que je ne peux pas résoudre. Voici mon code:

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

Et voici l'erreur que j'obtiens:

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
la source

Réponses:

161

Vous devez utiliser et définir l' maxBufferoption lors de l'utilisation child_process.exec. De la documentation :

maxBuffer spécifie la plus grande quantité de données autorisée sur stdout ou stderr - si cette valeur est dépassée, le processus enfant est tué.

La documentation indique également que la valeur par défaut maxBufferest de 200 Ko.

À titre d'exemple, la taille maximale de la mémoire tampon est augmentée à 500 Ko dans le code suivant:

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

De plus, vous voudrez peut-être lire l'article http.getpour voir s'il est capable de réaliser ce que vous essayez de faire.

Tim Cooper
la source
Cela a résolu mon problème, merci! Le dossier partagé est en fait sous le protocole webdav qui nécessite une authentification Digest, c'est pourquoi curl --digest http://login:password@" + ip + "/webdav/file.json
j'utilise
Cette valeur par défaut est ridiculement petite. C'est la deuxième fois que je suis mordu par cela d'une manière difficile à trouver.
jlh
3
La valeur par défaut est maintenant de 1 Mo @jlh, nodejs.org/api/…
Carlos
57

J'ai eu un problème similaire et je l'ai corrigé en passant de l'exécutif au 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);
});
lsampaio
la source
10
Cela semble être la solution la plus appropriée des deux
Hashbrown
1
Cette réponse n'est pas nécessairement la plus appropriée. Je pense que la sortie de la console dans la question pourrait être juste un exemple. Presque personne ne chercherait un fichier de 200 Ko pour le lancer dans la console. Cependant, si process.execest utilisé dans des choses comme les outils CLI, alors oui, le passage à spawndevrait être la voie à suivre.
Pavel Gatilov
1
wow ... le spawn est cool. Ce n'est même pas l'utilisation de rappels ou de promesses ... juste des événements. Cela pourrait être vraiment utile pour diffuser stdout sur la console. @ Pavel Gatilov, c'est exactement ce que nous faisons. FFMpeg aime montrer les progrès toutes les secondes ... ce qui pèse sur le tampon
Ray Foss