头有点大,这段时间一直在思考日志过滤问题,问题是实际生产环境中,开发者不同,且没有统一日志输出标准,导致日志输出格式不同(文件备份名不同、日期格式不同,输出格式不同,这都不是事,让我真正懵逼的是竟然把多个日志输出到一个文件中,估计是开发自己都没注意日志叠加输出了,哎,叠加输出时间戳就没办法搞了,我就真懵逼了。。。而且tail -f时出现文件被应用mv了o(╥﹏╥)o)
贴一个前段时间写的日志过滤脚本,实现效果,时间节点为单位,呈现时间节点的日志中字段出现位置及次数,并最终统计,因为错误大同小异,为了节省时间,做了每个时间点截取输出;如果把整个字段全部导出,再过滤会有消耗一定时间,但可以做时间节点标记,有兴趣的可以跟着思路再走一个脚本(字段忽略大小写)
我的思路:
获取字段出现的行,并向上、向下获取时间节点 h:mm:ss段(为什么不是hh,因为有个别日志是上午、下午 ),并截取这个时间节点内容到临时文件。
以我测试服务器做的范例效果如下:
脚本如下(几乎都做了注释,方便理解):
#!/bin/bash
#ffing.cn
read -p "请输文件路径(仅绝对路径或当前路径):" LOG
if [ ! -f "$LOG" ];then echo "路径不存在,请核实!";exit;fi
LOGPATH=$(readlink -f "$LOG")
read -p "请输过滤字段(可支持字符串中间空格):" VAR
if [ -z "$VAR" ];then echo "字段不能为空,请核实!";exit;fi
#字段出现总次数
COUNT=`grep -io "${VAR}" "$LOGPATH" | wc -l`
if [ $COUNT -eq 0 ];then "未从$LOGPATH过滤出字段$VAR";exit;fi
#信息展示
echo "字段出现次数:$COUNT"
echo "文件路径:$LOGPATH"
#获取所有出现的行号
ALLLINE=`grep -nio "${VAR}" $LOGPATH|cut -d":" -f1`
#初始值
#初始打印次数
PNUM=1
#初始字段列
FNUM=1
#临时文件路径
TMPLOG=/tmp/templogdisplay
#是否打印字段
echo "是否打印字段日志(过滤日志,需要等待一定时间:与文件大小、字段出现频率有关)"
read -p "请输入(回车或任意键回车,继续;ESC回车,退出):" KEY
case $KEY in
$'\E')
echo "未进行字段过滤,直接退出"
exit
;;
*)
;;
esac
#WHILE
while true
do
###获取字段所在行号
FLINE=`echo $ALLLINE|awk -v NNN=$FNUM '{print $NNN}'`
##################获取字段所在时间段内日志(若无时间节点则向上1000行)
##########打印起始位置到字段出现行号的日志到临时文件
##获取时间节点起始位置
#字段所在行是否有时间节点
sed -n "$FLINE"p $LOGPATH|grep "[0-9]:[0-9][0-9]:[0-9][0-9]" >/dev/null 2>&1
if [ $? -eq 0 ];then
STARTLINE=$FLINE
else
STARTLINE=$((FLINE-1000))
#判断起始行是否小于1,小于则改为1,保障起始行为正数
if [ $STARTLINE -lt 1 ];then
STARTLINE=1
fi
fi
#将起始行到字段行,内容导入到临时文件TMPLOG
sed -n "$STARTLINE,$FLINE"p $LOGPATH >$TMPLOG
#########对临时文件处理,删除字段所在时间节点之前的日志
#处理多余时间节点日志
#获取时间节点数量
TIMENUM=`grep "[0-9]:[0-9][0-9]:[0-9][0-9]" $TMPLOG|wc -l`
#时间节点数量大于等于2,证明多个时间节点,需删除多余的时间节点
if [ $TIMENUM -ge 2 ];then
#获取最后一个时间节点行号
ENDLINE=`grep -n "[0-9]:[0-9][0-9]:[0-9][0-9]" $TMPLOG|tail -n1|cut -d":" -f1`
#删除多余的时间节日志,从第一行到最后一个时间节点的上一行
sed -i "1,$((ENDLINE-1))"d $TMPLOG
fi
##########打印字段出现行号到+1000行的日志到临时文件
sed -n "$((FLINE+1)),+1000"p $LOGPATH>>$TMPLOG
##########对临时文件处理,删除字段所在时间点之后的日志
#处理多余时间节点日志
#获取时间节点数量
TIMENUM=`grep "[0-9]:[0-9][0-9]:[0-9][0-9]" $TMPLOG|wc -l`
#时间节点数量大于等于2,证明多个时间节点,需删除多余的时间节点
if [ $TIMENUM -ge 2 ];then
#获取第二个时间节点行号
ENDLINE=`grep -n "[0-9]:[0-9][0-9]:[0-9][0-9]" $TMPLOG|awk 'NR==2'|cut -d":" -f1`
#删除多余的时间节点日志,从第二个时间节点到文件结尾行
sed -i "$ENDLINE,$"d $TMPLOG
fi
##########现在TMPLOG中保留的是第一个时间节点中出现的字段(字段可能是一个、也可能是多个)
#统计TMPLOG中出现的字段数量
TMPCOUNT=`grep -io "$VAR" $TMPLOG|wc -l`
#########打印日志内容
echo
echo "第$PNUM个时间节点,当前时间节点出现<<< $VAR >>>字段为$TMPCOUNT处"
echo "=======================过滤字符串将以<<< >>>标识======================="
cat $TMPLOG |sed "s/$VAR/<<<&/ig;s/$VAR/&>>>/ig"
echo "======================================================================="
#下次打印字段位于第几处
FNUM=$((TMPCOUNT+FNUM))
##剩余字段数量
RCOUNT=$((COUNT-FNUM+1))
#是否继续打印
#判断是否打印完成所有字段
if [ $FNUM -gt $COUNT ];then
echo "#################所有字段印完成!##################"
echo "文件$LOGPATH"
echo "字段$VAR:共出现在$PNUM个时间节点,共出现$COUNT处。"
exit
else
echo "字段$VAR,总计$COUNT处,剩余$RCOUNT处,是否继续打印第$FNUM 处"
read -p "请输入(回车或任意键回车,继续;ESC回车,退出):" KEY
case $KEY in
$'\E')
echo "还有$RCOUNT 处未打印,提前退出"
exit
;;
*)
;;
esac
fi
let PNUM++
done
发表评论