awk、pipe 和 tail -f 给出意外行为

Har*_*rma 4 linux bash awk pipe tail

这是我的示例日志文件。http://pastebin.com/DwWeFhJk

当我在做

tail -f log | awk '{if (NF>3) {print $1}; }'
Run Code Online (Sandbox Code Playgroud)

我得到的结果是正确的

64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
64.242.88.10
Run Code Online (Sandbox Code Playgroud)

但是当我这样做时:

tail -f log |
awk '{if (NF>3) {print $1}; }' |
awk '{print $1}'
Run Code Online (Sandbox Code Playgroud)

我没有得到任何输出。甚至没有输出的情况下

tail -f log | awk '{if (NF>3) {print $1}; }' | grep "64"
Run Code Online (Sandbox Code Playgroud)

我不明白为什么第一个的输出awk没有作为第二个awk/grep管道之后的输入传递。

Jon*_*ler 5

当第一个输出awk到达终端时,输出是行缓冲的,因此每一行都在生成时打印。当输出进入第二个awk或 时grep,它被完全缓冲。在缓冲区已满之前不会发送输出。当足够多的额外记录附加到日志中时,第二awk个缓冲区将充满要处理的数据。在那之前,什么都不会发生。


小智 5

你开始命令 tail -f,这会使输出保持打开状态,因此不会向其他命令发送所需的换行符。

这工作得很好:

cat log | awk '{if (NF>3) {print $1}; }' | grep 64
Run Code Online (Sandbox Code Playgroud)

所以,问题是缓冲。中间的 awk 正在做普通缓冲而不是交互式缓冲。这适用于(不可移植)mawk:

tail -f log | mawk -W interactive '{if (NF>3) {print $1}; }' | awk '{print}'
Run Code Online (Sandbox Code Playgroud)

您可以阅读该问题的 GNU 描述

在任何情况下,只需检查中间使用的 awk 是否可以被告知交互式缓冲。

添加:

命令 system("") 似乎解除了缓冲的阻塞。它是 POSIX,但不适用于 mawk。

tail -f log | awk '{if (NF>3) {print $1}; system("")}' | awk '{print}'
Run Code Online (Sandbox Code Playgroud)