shell 日志字段过滤脚本

shell 日志字段过滤脚本

头有点大,这段时间一直在思考日志过滤问题,问题是实际生产环境中,开发者不同,且没有统一日志输出标准,导致日志输出格式不同(文件备份名不同、日期格式不同,输出格式不同,这都不是事,让我真正懵逼的是竟然把多个日志输出到一个文件中,估计是开发自己都没注意日志叠加输出了,哎,叠加输出时间戳就没办法搞了,我就真懵逼了。。。而且tail -f时出现文件被应用mv了o(╥﹏╥)o)

贴一个前段时间写的日志过滤脚本,实现效果,时间节点为单位,呈现时间节点的日志中字段出现位置及次数,并最终统计,因为错误大同小异,为了节省时间,做了每个时间点截取输出;如果把整个字段全部导出,再过滤会有消耗一定时间,但可以做时间节点标记,有兴趣的可以跟着思路再走一个脚本(字段忽略大小写)

我的思路:

获取字段出现的行,并向上、向下获取时间节点 h:mm:ss段(为什么不是hh,因为有个别日志是上午、下午 ),并截取这个时间节点内容到临时文件。

以我测试服务器做的范例效果如下:

https://qnimg.ffing.cn/wp-content/uploads/2022/03/image-27.png?imageView2/0/q/75|watermark/1/image/aHR0cHM6Ly9xbmltZy5mZmluZy5jbi9mbl9sb2dvLnBuZw==/dissolve/55/gravity/SouthEast/dx/0/dy/0

脚本如下(几乎都做了注释,方便理解):

#!/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

good good study, day day up!

发表评论

textsms
account_circle
email

shell 日志字段过滤脚本
头有点大,这段时间一直在思考日志过滤问题,问题是实际生产环境中,开发者不同,且没有统一日志输出标准,导致日志输出格式不同(文件备份名不同、日期格式不同,输出格式不同,这都不是…
扫描二维码继续阅读
2022-03-21