我在 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 却不能。