tail-pipe-awk 脚本,在 Centos 上很好,但在 Ubuntu 上很奇怪

tail-pipe-awk 脚本,在 Centos 上很好,但在 Ubuntu 上很奇怪

我在 CentOS 上写了一个脚本,现在我试图在 Ubuntu 上运行它,但它的行为出乎意料。下面是类似这样的脚本,我在 bash 下运行它:

sudo tail -F /var/opt/my-application/log/my-application.log |
awk '
BEGIN {
    ORS=" "
}
{ if ($8 ~ /MATCH-TEXT/) {
            # do a whole bunch of stuff here
            # like look in /proc and calculate CPU and interface stats
    };
 };
} '

以前,当我的日志的 $8 字段中出现带有 MATCH-TEXT 的行时,所有“执行大量操作”(脚本的核心)都会发生,并且我会看到输出。我的应用程序大约每秒生成一次 MATCH-TEXT 行(有时多,有时少),此脚本的输出也是如此。

但是现在,当我启动此脚本时,很长时间没有输出,然后一次输出大约 30 行。似乎脚本正在排队接收日志行,然后快速执行多次,因为 CPU 和界面上的计算适合“从一秒钟前开始”,而不是“从一秒钟前开始”。

更奇怪的是,注释掉 awk 命令的所有主要部分并将其替换为“print $0”(将整个脚本变成一个笨拙的 grep 命令)会产生相同的结果。因此,我相信这是系统执行此脚本的方式,而不是脚本本身的问题。

同时,在另一个窗口中,简单的“sudo tail -F my-application.log | grep MATCH-TEXT”每隔一秒左右就会得到输出(正如预期的那样)。

知道这是怎么回事吗?有什么提示我应该从哪里开始寻找导致这种排队行为的原因吗?

答案1

如果这不是由于 的差异造成的tail,那么我同意 Hauke Laging 的观点,这可能是缓冲问题。要刷新 的输出缓冲区awk,请尝试在打印语句后添加fflush(),就像我在以下测试代码中所做的那样:

tail -F /var/log/apache2/access_log | awk '{ if ($8 ~ /MATCH-TEXT/) { print $0; fflush(); }}'

答案2

mawk -W interactive 解决了我在 Debian Wheezy 上的问题。

    tail -f data.log | grep --line-buffered '$DataString' | mawk -W interactive -F "," '{print "var2", $2, "var4", $4}'

答案3

在研究了所有答案并尝试了 fflush 和 stdbuf(我以前不知道,谢谢)之后,我发现答案分为两部分:

1)CentOS 使用 gawk,Ubuntu 使用 mawk(默认)。

我无法评论哪一个更好或者为什么决定使用其中任何一个,差异就是这两个分布的不同之处。 (:

2)mawk 有一个“交互式”的命令行选项,来自手册页:

 -W interactive

 sets unbuffered writes to stdout and line buffered reads from stdin.
 Records from stdin are lines regardless of the value of RS.

我只能假设这是因为缓冲是在 awk 内而不是在脚本本身中,这使得它能够工作而 stdbuf 却不能。

相关内容