【问题标题】:Node.js: Capture STDOUT of `child_process.spawn`Node.js:捕获`child_process.spawn`的STDOUT
【发布时间】:2015-08-17 11:10:28
【问题描述】:

我需要在自定义中捕获生成的子进程的输出。

child_process.spawn(command[, args][, options])

例如,

var s = fs.createWriteStream('/tmp/test.txt');
child_process.spawn('ifconfig', [], {stdio: [null, s, null]})

现在如何实时读取/tmp/test.txt

看起来child_process.spawn 没有使用stream.Writable.prototype.writestream.Writable.prototype._write 来执行它。

例如,

s.write = function() { console.log("this will never get printed"); };

还有,

s.__proto__._write = function() { console.log("this will never get printed"); };

看起来它使用文件描述符在后台child_process.spawn写入文件。

这样做不起作用:

var s2 = fs.createReadStream('/tmp/test.txt');
s2.on("data", function() { console.log("this will never get printed either"); });

那么,如何获取子进程的STDOUT 内容?

我想要实现的是将子进程的STDOUT 流式传输到套接字。如果我将套接字作为stdio 参数直接提供给child_process.spawn,它会在完成时关闭套接字,但我想保持打开状态。

更新:

解决方法是使用默认的{stdio: ['pipe', 'pipe', 'pipe']}选项,监听子进程创建的.stdout

var cmd = child_process.spaw('ifconfig');
cmd.stdout.on("data", (data) => { ... });

现在,为了提高赌注,一个更具挑战性的问题:

-- 怎么读取子进程的STDOUT 还保留颜色?

例如,如果您像这样将STDOUT 发送到process.stdout

child_process.spawn('ifconfig', [], {stdio: [null, process.stdout, null]});

它将保留颜色并将彩色输出打印到控制台,因为 process.stdout 上的 .isTTY 属性设置为 true

process.stdout.isTTY // true

现在,如果您使用默认的{stdio: ['pipe', 'pipe', 'pipe']},您将读取的数据将被去除控制台颜色。你是怎么得到颜色的?

一种方法是使用fs.createWriteStream 创建您自己的自定义流,因为child_process.spawn 要求您的流具有文件描述符。

然后将该流的.isTTY 设置为true,以保留颜色。

最后,您需要捕获child_process.spawn 写入该流的数据,但由于child_process.spawn 不使用流的.prototype.write.prototype._write,您需要在其他一些地方捕获其内容hacky 方式。

这可能就是child_process.spawn 要求您的流具有文件描述符的原因,因为它绕过了.prototype.write 调用并直接写入文件幕后

有什么想法可以实现吗?

【问题讨论】:

    标签: javascript node.js stream


    【解决方案1】:

    你可以不使用临时文件来做到这一点:

    var process = child_process.spawn(command[, args][, options]);
    process.stdout.on('data', function (chunk) {
        console.log(chunk);
    });
    

    【讨论】:

    • 这是否实际上阻塞了语句之间的输出流,或者该间隔内的任何输出都丢失了?
    • @AsadSaeeduddin 不,它不会阻止。
    【解决方案2】:

    您好,我正在打电话,但我会尽力为您提供指导。如果需要,我会在靠近计算机时澄清

    我认为您想要的是从 spawn 中读取 stdout 并对数据进行处理?

    你可以给 spawn 一个变量名而不是仅仅运行函数,例如:

    var child = spawn();
    

    然后听如下输出:

    child.stdout.on('data', function(data) {
        console.log(data.toString());
    });
    

    您可以使用它来将数据写入文件或您可能想要对其执行的任何操作。

    【讨论】:

    • 感谢您的快速回复!
    【解决方案3】:

    stdio 选项需要文件描述符,而不是流对象,因此一种方法是使用 fs.openSync() 创建一个输出文件描述符,然后我们就可以了。

    以你的第一个例子,但使用fs.openSync()

    var s = fs.openSync('/tmp/test.txt', 'w');
    var p = child_process.spawn('ifconfig', [], {stdio: [process.stdin, s, process.stderr]});
    

    您还可以将 stdout 和 stderr 设置为相同的文件描述符(与 bash 的 2>&1 效果相同)。

    完成后您需要关闭文件,所以:

    p.on('close', function(code) {
      fs.closeSync(s);
      // do something useful with the exit code ...
    });
    

    【讨论】:

      猜你喜欢
      • 2016-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 2019-11-14
      • 2013-01-12
      • 1970-01-01
      相关资源
      最近更新 更多