读取node.js中child_process.spawn的stderr的所有内容

时间:2019-06-05 12:14:26

标签: node.js buffer child-process

尝试通过fping从nodejs运行child_process.spawn()并通过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 个答案:

答案 0 :(得分:1)

您应该收听end事件。 data事件可能被多次调用-每个接收到的块都被调用。所有块都应收集在一起,例如以数组的形式。 end事件表示该可读流(child.stderr)中没有更多数据要消耗。

请参见以下使用end事件对代码进行略微更改的版本(使用setTimeout和ping代替):

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