Child_process düğümünü kullanan stdout arabellek sorunu


92

Yerel bir ağdaki paylaşılan bir klasörden bir JSON dosyası (yaklaşık 220Ko) almak için child_process düğümünü kullanarak curl'yi yürütmeye çalışıyorum. Ama aslında aklıma gelmeyen bir tampon problemi veriyor. İşte kodum:

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

Ve işte aldığım hata:

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)

Yanıtlar:


161

maxBufferKullanırken seçeneği kullanmanız ve ayarlamanız gerekir child_process.exec. Gönderen belgeler :

maxBuffer stdout veya stderr'de izin verilen en büyük veri miktarını belirtir - bu değer aşılırsa, alt süreç öldürülür.

Belgelerde ayrıca varsayılan değerin maxBuffer200 KB olduğu belirtilmektedir.

Örnek olarak, aşağıdaki kodda maksimum arabellek boyutu 500KB'ye yükseltilmiştir:

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

Ek olarak, http.getyapmaya çalıştığınız şeyi başarabilecek durumda olup olmadığını öğrenmek için okumak isteyebilirsiniz .


Bu benim sorunumu çözdü, teşekkürler! Paylaşılan klasör aslında özet kimlik doğrulaması gerektiren webdav protokolü altındadır, bu yüzden onu çok kolay bir şekilde işleyen curl kullanıyorumcurl --digest http://login:password@" + ip + "/webdav/file.json
Yonnaled,

Bu varsayılan, gülünç derecede küçüktür. Bu, bulması zor bir şekilde ikinci kez ısırıldım.
jlh

3
Varsayılan değer şimdi 1MB @jlh, nodejs.org/api/…
Carlos

57

Benzer bir sorun yaşadım ve exec'den spawn'a geçişi düzelttim:

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
Bu ikisinin en uygun çözümü gibi görünüyor
Hashbrown

1
Bu cevap mutlaka en uygun olanı değil. Bence sorudaki konsol çıktısı sadece bir örnek olabilir. Neredeyse hiç kimse konsola atmak için 200KB'lik bir dosya getirmez. Bununla birlikte, process.execCLI araçları gibi şeylerde kullanılıyorsa, o zaman evet, geçiş spawnyapmanın yolu olmalıdır.
Pavel Gatilov

1
vay ... spawn harika. Geri arama veya vaatleri bile kullanmıyor ... sadece olaylar. Bu, stdout'u konsola aktarmak için gerçekten yararlı olabilir. @Pavel Gatilov, tam olarak yaptığımız şey bu. FFMpeg her saniye ilerleme göstermeyi seviyor ... bu da arabelleğe zarar
Ray Foss
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.