我想实时阅读和解析(awk
)我的nginx日志。所以我编写了这个shell命令来执行此操作,如果我在shell中运行它会起作用:
tail -f -n +1 /var/log/nginx/access.log | awk '{print $1, $7, $9}'
但是我无法在节点中运行它。我编写了这段代码来运行我的命令(这是从node.js文档中的示例中获取的),但它没有显示任何内容:
const tail = childProcess.spawn('tail',['-f', '-n', '+1', nginxAccessLog]);
const awk = childProcess.spawn('awk', ['{print $1, $7, $9}'], { 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
输出中),但我没有输出。
我该如何解决这个问题?
答案 0 :(得分:1)
不太确定为什么将tail.stdout
传递给Awk流程并不起作用(我猜测在创建Awk流程时,tail.stdout
可能还没有附加到它的有效文件描述符),但这样做:
const tail = childProcess.spawn('tail',['-f', '-n', '+1', nginxAccessLog]);
const awk = childProcess.spawn('awk', ['{print $1, $7, $9}'], { stdio: [ 'pipe', process.stdout ] });
tail.stdout.pipe(awk.stdin);
请注意,由于您正在使用tail -f
,因此管道将继续运行。
编辑:如果您不打算只记录输出,而且还要处理它,情况会变得更加复杂,因为Awk缓冲了它输出(我相信最高4K)。
您需要在Awk中强制刷新,fflush("")
或system("")
可以触发I found。所以代码变成了:
const tail = childProcess.spawn('tail',['-f', '-n', '+1', nginxAccessLog]);
const awk = childProcess.spawn('awk', [ '{print $1, $7, $9; fflush(""); }']);
tail.stdout.pipe(awk.stdin);
awk.stdout.on('data', data => {
console.log('awk output:', data.toString());
});
这似乎在输出中添加了空行,但我猜这些可以过滤掉。