使用循环仅搜索时间窗口中的日志

时间:2018-07-09 12:55:26

标签: bash shell sed grep

我正在尝试在日志文件中查找最近5分钟的模式“ INFO:服务器启动”。

这是我要从中查找模式的行:“ INFO | jvm 1 | main | 2018/07/09 00:11:29.077 | INFO:服务器启动时间为221008 ms”

模式即将来临,但是我需要缩短代码或为其创建循环。

我试图创建一个循环,但无法正常工作。这是我的没有循环的代码,可以正常工作:

#!/bin/bash
#Written by Ashutosh
#We will declare variables with date and time of last 5 mins.
touch /tmp/a.txt;
ldt=$(date +"%Y%m%d");
cdt=$(date +"%Y/%m/%d %H:%M");
odtm5=$(date +"%Y/%m/%d %H:%M" --date "-5 min");
odtm4=$(date +"%Y/%m/%d %H:%M" --date "-4 min");
odtm3=$(date +"%Y/%m/%d %H:%M" --date "-3 min");
odtm2=$(date +"%Y/%m/%d %H:%M" --date "-2 min");
odtm1=$(date +"%Y/%m/%d %H:%M" --date "-1 min");

## Finding the pattern and storing it in a file
grep -e "$odtm1" -e "$cdt" -e "$odtm2" -e "$odtm3" -e "$odtm4" -e 
"$odtm5" /some/log/path/console-$ldt.log 
> /tmp/a.txt;
out=$(grep 'INFO: Server startup in' /tmp/a.txt);
echo "$out" 

## remove the file that contains the pattern
rm /tmp/a.txt;

我也尝试使用sed,但是date函数无法使用它。 有人可以给我新的带循环的更改脚本吗?

3 个答案:

答案 0 :(得分:4)

采用原始逻辑:

time_re='('
for ((count=5; count>0; count--)); do
  time_re+="$(date +'%Y/%m/%d %H:%M' --date "-$count min")|"
done
time_re+="$(date +'%Y/%m/%d %H:%M'))"

ldt=$(date +'%Y%m%d')

awk -v time_re="$time_re" '
  $0 ~ time_re && /INFO: Server startup in/ { print $0 }
' "/some/log/path/console-$ldt.log"

性能增强当然是可能的-通过将日志分为开始时间可以使速度更快-但上面的内容解决了明确的问题(关于使用循环生成时间窗口的问题)。请注意,它变得笨拙-例如,您不希望使用它来搜索最后一天,因为正则表达式将变得完全不合理。

答案 1 :(得分:1)

您需要的声音是:

nil

不需要显式循环或多次调用NoMethod Error for nil class

答案 2 :(得分:1)

这里有一个bash脚本可以完成任务(感谢Charles的改进):

#!/bin/bash
limit=$(date -d '5 minutes ago' +%s)
today_logs="/some/log/path/console-$(date +'%Y%m%d').log"
yesterday_logs="/some/log/path/console-$(date +'%Y%m%d' -d yesterday).log"

tac "$today_logs" "$yesterday_logs" \
| while IFS='|' read -r prio jvm app date log; do
    [ $(date -d "$date" +%s) -lt "$limit" ] && break
    echo "|$jvm|$prio|$app|$date|$log"
done \
| grep -F 'INFO: Server startup in' \
| tac

与原始脚本相比,它具有以下优点:

  • 已优化:从最近的日志行开始分析,并在遇到的第一行超过5分钟的行处停止。在23:59,无需解析从0:00到23:53的日志行
  • 任意时间窗口:您可以将“ 5分钟”替换为“ 18小时”,并且仍然可以使用。超过一天的时间窗口需要调整,因为每天都有自己的日志文件
  • 当日期更改时可以正常工作:在0:00时,原始脚本永远不会解析23:55:00至23:59:59的日志行

将上面的代码与Ed Morton's answer混合,您将得到:

#!/bin/bash
limit=$(date -d '5 minutes ago' +'%Y/%m/%d %H:%M')
today_logs="/some/log/path/console-$(date +'%Y%m%d').log"
yesterday_logs="/some/log/path/console-$(date +'%Y%m%d' -d yesterday).log"

tac "$today_logs" "$yesterday_logs" \
| awk -v stop="$limit" -F'[[:space:]]*[|][[:space:]]*' '
    ($4 < stop) { exit }
    /INFO: Server startup in/
' \
| tac