Читать все из stderr child_process.spawn в nodejs - PullRequest
0 голосов

Попытка запустить fping из nodejs через child_process.spawn() is и захват вывода через cp.stderr.on('data') иногда приводят к неполным данным в буфере. Вот мой образец фрагмента:

const ChildProcess = require('child_process');

const args = [
                '-A','-c10','-b1472','-B1',
                '-r0','-O0','-q', '-p100',
                'google.com', 'slack.com', 'github.com'
            ];

function runChildProcess() {
    const child = ChildProcess.spawn('fping', args);

    child.on('exit', (code) => 
        console.log('Process exited with code', code)
    );

    child.stdout.on('data', (data) => {
        console.log('stdout:', data.toString().length, 'chars');
    });
    child.stderr.on('data', (data) => {
        console.log('stderr:', data.toString().length, 'chars');
    });

}

setInterval(runChildProcess, 1500);

Это производит вывод примерно так:

stderr: 219 chars
Process exited with code 0
stderr: 208 chars
stderr: 11 chars
Process exited with code 0
stderr: 218 chars
stderr: 1 chars
Process exited with code 0
stderr: 219 chars
Process exited with code 0
stderr: 219 chars
Process exited with code 0
stderr: 219 chars
Process exited with code 0
stderr: 218 chars
stderr: 1 chars
Process exited with code 0

Как видите, иногда он вызывает обратный вызов два раза, иногда один, у меня были случаи, когда он вызывался 3 или 4 раза с небольшими чтениями. Есть ли способ обеспечить чтение всех доступных данных, а не только некоторых из них?

1 Ответ

1 голос
/ 05 июня 2019

Вы должны прослушать событие end. Событие data может вызываться несколько раз - оно вызывается для каждого полученного фрагмента. Все куски должны быть собраны вместе, например, в массив. Событие end сигнализирует, что в этом читаемом потоке больше нет данных для потребления (child.stderr).

См. Ниже слегка измененную версию вашего кода (вместо setTimeout и ping), используя событие end:

const ChildProcess = require('child_process');

const args = [
                'google.com'
            ];

function runChildProcess() {
    var stdoutChunks = [], stderrChunks = [];
    const child = ChildProcess.spawn('ping', args);

    child.on('exit', (code) =>
        console.log('Process exited with code', code)
    );

    child.stdout.on('data', (data) => {
        stdoutChunks = stdoutChunks.concat(data);
    });
    child.stdout.on('end', () => {
        var stdoutContent = Buffer.concat(stdoutChunks).toString();
        console.log('stdout chars:', stdoutContent.length);
        console.log(stdoutContent);
    });

    child.stderr.on('data', (data) => {
        stderrChunks = stderrChunks.concat(data);
    });
    child.stderr.on('end', () => {
        var stderrContent = Buffer.concat(stderrChunks).toString();
        console.log('stderr chars:', stderrContent.length);
        console.log(stderrContent);
    });

}

setTimeout(runChildProcess, 0);
...