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

时间:2017-04-18 09:43:17

标签: node.js shell nginx pipe child-process

我想实时阅读和解析(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输出中),但我没有输出。 我该如何解决这个问题?

1 个答案:

答案 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());
});

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