2012-07-13 130 views
5

我试图设置一个脚本,当某个字符串出现在日志文件中时会生成警报。如何将tail -f拖入awk

已经到位的解决方案里grep整个日志文件每分钟一次,并计数串出现的频率,使用日志行的时间戳来算只有前一分钟发生。

我想这将是更有效的带尾巴要做到这一点,所以我尝试了以下方面的测试:

FILENAME="/var/log/file.log" 

tail -f $FILENAME | awk -F , -v var="$HOSTNAME" ' 
       BEGIN { 
         failed_count=0; 
       } 
       /account failure reason/ { 
         failed_count++; 
       } 
       END { 
         printf("%saccount failure reason (Errors per Interval)=%d\n", var, failed_count); 
       } 
' 

但这只是挂不输出任何东西。有人提出这个小小的变化:

FILENAME="/var/log/file.log" 

awk -F , -v var="$HOSTNAME" ' 
       BEGIN { 
         failed_count=0; 
       } 
       /account failure reason/ { 
         failed_count++; 
       } 
       END { 
         printf("%saccount failure reason (Errors per Interval)=%d\n", var, failed_count); 
       } 
' <(tail -f $FILENAME) 

但这样做的事情。

我正在使用的awk(我在上面的代码中已经简化了)的工作原理,因为它用于现有脚本中,其中grep“^ $ TIMESTAMP”的结果已被传入。

我的问题是,怎样才能得到尾-f使用awk工作?

+4

当你'tail -f'时,你的awk脚本永远不会到达END。所以你不断计算错误,但从不打印任何东西。您需要运行printf并重置计数器的另一个条件(例如,检测到它是新的一天)。向我们展示您的日志样本,我们可以提出修正建议。 – ghoti 2012-07-13 11:57:32

回答

4

假设您的日志看起来是这样的:

Jul 13 06:43:18 foo account failure reason: unknown 
│ │  
│ └── $2 in awk 
└────── $1 in awk 

你可以做这样的事情:

FILENAME="/var/log/file.log" 

tail -F $FILENAME | awk -v hostname="$HOSTNAME" ' 
    NR == 1 { 
     last=$1 " " $2; 
    } 
    $1 " " $2 != last { 
     printf("%s account failure reason (Errors on %s)=%d\n", hostname, last, failed); 
     last=$1 " " $2; 
     failed=0; 
    } 
    /account failure reason/ { 
     failed++; 
    } 
' 

请注意,我已经改变了这tail -F(大写F),因为它处理日志老化。这在每个操作系统中都不被支持,但它应该在现代BSD和Linuces中运行。

这是如何工作的?

的awk脚本包括套test { commands; }对输入的每一行评价。 (有两个特殊的测试,BEGINEND其命令运行时AWK开始,当awk的两端,分别在你的问题,AWK永不落幕,所以END代码是永远不会运行。)

上面的脚本有三个测试/命令部分:

  • 第一个,NR == 1是一个测试,仅在输入的第一行评估为真。它运行的命令创建了last变量的初始值,在下一节中使用。
  • 在第二部分中,我们测试自上一行评估以来“最后”变量是否发生了变化。如果这是真的,则表示我们正在评估新的一天的数据。现在是时候打印上个月的摘要(日志),重置我们的变量并继续前进。
  • 第三,如果我们正在评估的行匹配正则表达式/account failure reason/,我们会增加计数器。

清除泥? :-)

+0

+1 - 为了做错误/日,你需要保持计数的日子,并进行分工。或者您可以将您的措辞更改为“昨天的错误”并重置“failed_count”。 – 2012-07-13 12:38:18

+0

哦,现货!不知道它在做什么,但很好,谢谢! – mazz0 2012-07-13 13:29:53

+0

@DennisWilliamson - 对,谢谢你指出。我已经更新了答案,以便代码提供更清晰的结果。 – ghoti 2012-07-13 20:04:01