Node.js: Capture STDOUT of `child_process.spawn`

Node.js: Capture STDOUT of `child_process.spawn`

本文关键字:child process spawn of js Capture STDOUT Node      更新时间:2023-09-26

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

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流到套接字。如果我将套接字直接提供给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属性在process.stdout上被设置为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,您需要以其他一些黑客方式捕获其内容。

这可能就是为什么child_process.spawn要求你的流有一个文件描述符,因为它绕过.prototype.write调用,直接写到文件

有什么想法如何实现这一点吗?

您可以不使用临时文件:

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

你好,我在打电话,但我会尽我所能指导你。如果需要,我会在电脑附近说明

我认为你想要的是从刷出中读取stdout并使用数据做一些事情?

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

var child = spawn();

然后听输出如下:

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

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

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的2>&1效果相同)。

完成后需要关闭文件,因此:

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