Node 的 childProcess.spawn - 管道不起作用

Node's childProcess.spawn - piping doesn't work

我想实时读取和解析(使用 awk)我的 nginx 日志。所以我写了这个 shell 命令来做到这一点,如果我 运行 它在 shell:

tail -f -n +1 /var/log/nginx/access.log | awk '{print , , }'

但我不能 运行 它在节点中。我将此代码写入 运行 我的命令(这是从 node.js 文档中的示例中获取的),但它什么也不显示:

const tail = childProcess.spawn('tail',['-f', '-n', '+1', nginxAccessLog]);
const awk = childProcess.spawn('awk', ['{print , , }'],  { stdio: [tail.stdout, 'pipe', 'pipe'] })
tail.stdout.on('data', (data) => {
  console.log('tail output', data.toString());
})
awk.stdout.on('data', (data) => {
  console.log('awk output', data.toString());
})
tail.on('error', () => 'tail error')
awk.on('error', () => 'awk error')
tail.on('close', () => console.log('tail end', result));
awk.on('close', () => console.log('awk end', result));

我可以看到我的进程已生成(它们在 htop 输出中),但我没有输出。 我该如何解决这个问题?

不太清楚为什么将 tail.stdout 传递给 Awk 进程不起作用(我猜测在创建 Awk 进程时,tail.stdout 可能还没有有效文件附加到它的描述符),但这确实:

const tail = childProcess.spawn('tail',['-f', '-n', '+1', nginxAccessLog]);
const awk  = childProcess.spawn('awk', ['{print , , }'],  { stdio: [ 'pipe', process.stdout ] });

tail.stdout.pipe(awk.stdin);

请注意,因为您使用的是 tail -f,管道将保持 运行。

编辑:如果你不打算只是记录输出,还要处理它,情况会变得更加复杂因为 Awk 缓冲它的输出(我相信最多 4K)。

您需要在 Awk 中强制刷新,I found 可以使用 fflush("")system("") 触发。所以代码变成:

const tail = childProcess.spawn('tail',['-f', '-n', '+1', nginxAccessLog]);
const awk  = childProcess.spawn('awk', [ '{print , , ; fflush(""); }']);

tail.stdout.pipe(awk.stdin);

awk.stdout.on('data', data => {
  console.log('awk output:', data.toString());
});

这似乎确实在输出中添加了空行,但我猜这些可以被过滤掉。