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());
});
这似乎确实在输出中添加了空行,但我猜这些可以被过滤掉。
我想实时读取和解析(使用 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());
});
这似乎确实在输出中添加了空行,但我猜这些可以被过滤掉。