gpt4 book ai didi

awk - 如何将 tail -f 通过管道传输到 awk 中

转载 作者:行者123 更新时间:2023-12-02 12:19:55 25 4
gpt4 key购买 nike

我正在尝试设置一个脚本,当日志文件中出现某个字符串时,会生成警报。

现有的解决方案每分钟对整个日志文件进行 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" 的结果通过管道传输到其中。

我的问题是,如何让 tail -f 与 awk 一起使用?

最佳答案

假设您的日志如下所示:

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 和 Linux 中工作。

这是如何工作的?

Awk 脚本由多组 test { 命令组成; } 针对每行输入进行评估。 (有两个特殊测试, BEGINEND ,它们的命令分别在 awk 启动和 awk 结束时运行。在您的问题中,awk 从未结束,因此 END 代码从未运行。)

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

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

清澈如泥? :-)

关于awk - 如何将 tail -f 通过管道传输到 awk 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11469959/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com