Node.js:捕获`child_process.spawn`

时间:2015-06-03 09:56:18

标签: javascript node.js stream

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

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

看起来它使用文件描述符 under-the-hood child_process.spawn写入文件。

这样做不起作用:

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

那么,我怎样才能获得子进程的STDOUT内容?

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

更新

解决方案是使用默认的{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]});

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

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调用并直接写入文件 under-the-hood

有任何想法如何实现这个?

3 个答案:

答案 0 :(得分:5)

您可以在不使用临时文件的情况下执行此操作:

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

答案 1 :(得分:2)

嗨,我在手机上,但我会尽力指导你。如果需要,我会在计算机附近澄清

我认为你想要的是从产卵中读取stdout并对数据做些什么?

您可以为spawn提供变量名称,而不是仅运行该函数,例如:

var child = spawn();

然后听取输出:

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

您可以使用它将数据写入文件或您可能想要使用的任何内容。

答案 2 :(得分:2)

stdio选项需要文件描述符,而不是流对象,所以一种方法是使用use 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' s 2>&1相同)。

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

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