gpt4 book ai didi

javascript - 如何从 child_process 中获取无缓冲或至少按顺序获取 stdout 和 stderr

转载 作者:行者123 更新时间:2023-12-03 06:56:55 24 4
gpt4 key购买 nike

这是一个简单的 Node 程序:(注意:这只是一个示例。替换任何同时输出到 stdout 和 stderr 的程序,如果这些行乱序,它们将没有那么有用,例如 llvm、gcc、clang、少,grep等...)

const log = msg => console.log(`log: ${msg}`);
const error = msg => console.error(`error: ${msg}`);

log('line1');
error('line2');
log('line3');
error('line4');
如果我运行它,我会得到以下输出:
log: line1
error: line2
log: line3
error: line4
现在我想要 child_process.execFile 的相同输出.问题是这些行被缓冲了,所以它们不会以相同的顺序到达我这里:
const child_process = require('child_process');
const lines = [];
const ch = child_process.execFile(process.argv[0], ['main.js'], () => {
console.log(lines.join(''));
});
ch.stdout.on('data', (data) => { lines.push(data); });
ch.stderr.on('data', (data) => { lines.push(data); });

产生:
log: line1
error: line2
error: line4
log: line3
作为另一个例子,这里有一个 bash 脚本:
#!/bin/sh
echo line 1
echo line 2 >&2
echo line 3
echo line 4 >&2
并在终端中运行它的输出是:
line 1
line 2
line 3
line 4
但通过 child_process 运行它:
const child_process = require('child_process');
const lines = [];
const ch = child_process.execFile('sh', ['test.sh'], () => {
console.log(lines.join(''));
});
ch.stdout.on('data', (data) => { lines.push(data); });
ch.stderr.on('data', (data) => { lines.push(data); });
输出:
line 1
line 3
line 2
line 4
我怎样才能以相同的顺序获得这些行,并且还知道哪些来自 stdout,哪些来自 stderr?
注意, the docs说一些关于缓冲的矛盾的事情。一方面他们说

By default, pipes for stdin, stdout, and stderr are established between the parent Node.js process and the spawned child. These pipes have limited (and platform-specific) capacity. If the child process writes to stdout in excess of that limit without the output being captured, the child process will block waiting for the pipe buffer to accept more data


但后来他们提到了一个设置, maxBuffer它说

maxBuffer Largest amount of data in bytes allowed on stdout or stderr. If exceeded, the child process is terminated and any output is truncated


这两种解释似乎相互矛盾。我想也许设置 maxBuffer到 0 可能是解决方案,但显然不是。
无论如何,虽然不清楚如何取消缓冲这些流。 spawn本身有 an example in the docs但尝试一下
const child_process = require('child_process');
const lines = [];
const ch = child_process.spawn(process.argv[0], ['main.js']);

ch.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});

ch.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});

ch.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
导致相同的结果
stdout: log: line1

stderr: error: line2
error: line4

stdout: log: line3

child process exited with code 0
我怀疑这与制作 Writeable 有关流并通过 spawn 传入但目前尚不清楚如何做到这一点。我尝试创建一个 Writeable并将其传入但 Node 提示
internal/child_process.js:996
throw new ERR_INVALID_OPT_VALUE('stdio', inspect(stdio));
^

TypeError [ERR_INVALID_OPT_VALUE]: The value "Writable {
_writableState: WritableState {
objectMode: false,
highWaterMark: 0,
finalCalled: false,
needDrain: false,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: true,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
afterWriteTickInfo: null,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: false,
errorEmitted: false,
emitClose: true,
autoDestroy: false,
bufferedRequestCount: 0,
corkedRequestsFree: {
next: null,
entry: null,
finish: [Function: bound onCorkedFinish]
}
},
writable: true,
_write: [Function: write],
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
[Symbol(kCapture)]: false
}" is invalid for option "stdio"
知道如何在 Node 中生成子进程时同步或至少正确地交错捕获 stdout 和 stderr 吗?

我认为我正在尝试做的事情显然是不可能的。 IIUC 我需要为 stdout 和 stderr 传递相同的流,以确保它们正确交错,一旦我这样做,我就失去了判断输出来源的能力。
但是,如果没有别的,我需要立即得到结果(无缓冲)。想象一下,我正在制作一个基于 Node 的终端并运行命令,该输出需要返回给我,以便我可以显示它(如基于文本的微调器),就好像它被缓冲(这是我现在看到的)我会只能在卡盘中获得输出。

最佳答案

恐怕你所做的

const child_process = require('child_process');
const lines = [];
const ch = child_process.execFile('sh', ['test.sh'], () => {
console.log(lines.join(''));
});
ch.stdout.on('data', (data) => { lines.push(data); });
ch.stderr.on('data', (data) => { lines.push(data); });
是我们能做的最大值。您的测试脚本的问题
#!/bin/sh
echo line 1
echo line 2 >&2
echo line 3
echo line 4 >&2
是这两个字符串 "line 1\n""line 3\n"写得这么快。
我的意思是:从子级到父级的数据传输由操作系统处理,该操作系统(可能)使用低级管道或任何其他类型的缓冲区。即使 child 无缓冲地写入 stdout发生什么事? child 写 "line 1\n" ,操作系统将其缓冲在某处并向父级发送信号,该信号上升到最终需要读取的父级;如果在这段时间 child 写 "line 3\n"同样,操作系统除了缓冲它(使用先前写入的数据)之外别无他法,因此当父级最终读取数据时,无法知道完成了多少(非缓冲)写入来写入它。

关于javascript - 如何从 child_process 中获取无缓冲或至少按顺序获取 stdout 和 stderr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63791630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com