Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从child_进程中取消缓冲或至少按顺序获取stdout和stderr_Javascript_Node.js - Fatal编程技术网

Javascript 如何从child_进程中取消缓冲或至少按顺序获取stdout和stderr

Javascript 如何从child_进程中取消缓冲或至少按顺序获取stdout和stderr,javascript,node.js,Javascript,Node.js,下面是一个简单的节点程序:(注意:这只是一个示例。替换任何同时输出到stdout和stderr的程序,如果这些行的顺序不正确,它们就没有那么有用了,例如llvm、gcc、clang、less、grep等等。) 如果我运行它,我会得到以下输出: log: line1 error: line2 log: line3 error: line4 现在我希望从child\u process.execFile获得相同的输出。问题是缓存了这些行,因此它们不会以相同的顺序到达我这里: const child_

下面是一个简单的节点程序:(注意:这只是一个示例。替换任何同时输出到stdout和stderr的程序,如果这些行的顺序不正确,它们就没有那么有用了,例如llvm、gcc、clang、less、grep等等。)

如果我运行它,我会得到以下输出:

log: line1
error: line2
log: line3
error: line4
现在我希望从
child\u 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
但是通过
子进程运行它

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的

注意,这里提到了一些关于缓冲的相互矛盾的事情。一方面他们说

默认情况下,stdin、stdout和stderr的管道在父Node.js进程和生成的子进程之间建立。这些管道的容量有限(且特定于平台)。如果子进程在未捕获输出的情况下写入stdout超过该限制,则子进程将阻止等待管道缓冲区接受更多数据

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

maxBuffer在stdout或stderr上允许的最大数据量(字节)。如果超出,则终止子进程并截断任何输出

这两种解释似乎有冲突。我认为将
maxBuffer
设置为0可能是解决方案,但显然不是

在任何情况下,尽管还不清楚如何解除这些流的缓冲

spawn
本身就有,但正在尝试

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
我怀疑这与制作一个
可写的
流并使用
spawn
将其传入有关,但不清楚如何做到这一点。我试图创建一个
可写的
并将其传入,但没有成功

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"
在节点中生成子进程时,您知道如何同步或至少正确地交错捕获stdout和stderr吗


我想我要做的显然是不可能的。IIUC我需要在同一个流中传递stdout和stderr,以使它们正确地交错,一旦我这样做,我就失去了分辨输出来自何处的能力


但是,如果没有其他事情,我需要立即(无缓冲)得到结果。想象一下,我正在制作一个基于节点的终端并运行命令,该输出需要返回给我,以便我可以显示它(如基于文本的微调器),在那里,好像它是缓冲的(这就是我现在看到的),我将只获取卡盘中的输出。

如果修改实际的子进程是一个选项,您可以在写入每一行后通过刷新来强制它同步记录

main.js
示例:

var logbuffer = require('log-buffer');

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

log('line1');
error('line2');
log('line3');
error('line4');
否则,如控制台的Node.js中所述,控制台实例被配置为写入
process.stdout
process.stderr
。以下详细描述了它们的同步/异步:


恐怕你所做的

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
就是两个字符串
“第1行\n”
“第3行\n”
写得太快了


我的意思是:从子级到父级的数据传输由操作系统处理,操作系统(可能)使用低级管道或任何其他类型的缓冲区。即使孩子在未缓冲的情况下写入
stdout
会发生什么?子系统写入
“第1行\n”
,操作系统将其缓冲在某个地方,并向父系统发送信号,该信号上升到最终需要读取的父系统;如果在这段时间内,子系统也写入
“第3行\n”
,那么操作系统除了缓冲它(使用以前写入的数据)之外没有其他方法,因此当父系统最终读取数据时,无法知道写入数据时进行了多少次(无缓冲)写入。

我在节点
10.19.0
上运行,得到了1 2 3 4输出。你的节点版本是什么?我在节点12.18.0上进行MacOSE测试,你需要能够区分stderr和stdout吗?正如下面的评论所指出的,使用与stderr和stdout相同的文件可以获得您想要的顺序,但这意味着要写入文件,并且无法知道消息来自何处。是的,你需要知道。”out:file1’、‘error:fail’、‘out:file2’的含义与‘out:file1’、‘out-file2’、‘error:fail’的含义不同,这都是带有execFile的
echo-line 2>&2的。感谢您的建议。我无法控制我正在生成的程序。它们可以是任何东西,
rust
clang
make
git
,等等。。。所以我不能增加它们来冲水。我不知道你链接的那些文档是如何帮助你的。有没有办法将stdout和stderr设置为虚拟文件,以便我可以跨平台同步查看输出?谢谢您的确认。由于子进程可能是任意的,我认为您所描述的无法实现。引用的文档旨在强调Node.js
stdout
stderr
是独立的,并且根据各自的平台同步或异步运行。文档还说,如果传入文件,则所有平台都是同步的,因此我想知道是否有方法传入假/伪/虚拟文件这是无缓冲的,当生成的应用程序写入时,我可以从中读取
#!/bin/sh
echo line 1
echo line 2 >&2
echo line 3
echo line 4 >&2