linux 日志时间区间过滤(非连续时间戳)

linux 日志时间区间过滤(非连续时间戳)

sed过滤区间日志时,需要保障过滤的值必须存在,否则就会sed到日志结尾。

因此,当过滤时间区间日志是就需要去查找最近的时间戳。

我的这个脚本是针对一天的时间区间进行过滤(00:00:00-23:59:59),下面的脚本,是我从自己的脚本拆出来的,主要讲下思路,方便后期回忆。

下例:以过滤06:00至08:30之间的日志为例

范例:存在时间戳3:00:01、5:59:05、7:00:41、7:30:08、8:30:20、8:30:40

2022/03/01 03:00:01 [error] 1408#0: *54996 open() "/usr/share/nginx/phpinfo/ftptest.cgi" failed (2: No such file or directory), client: 23.95.100.141, server: , request: "GET /ftptest.cgi HTTP/1.0"
2022/03/01 05:59:05 [alert] 1408#0: *55032 open socket #5 left in connection 21
ffing cn
2022/03/01 07:00:41 [alert] 1408#0: aborting ffing cn
2022/03/01 07:30:08 [error] 1383#0: *14 open() "/usr/share/nginx/phpinfo/ftptest.cgi" failed (2: No such file or directory), client: 23.95.100.141, server: , request: "GET /ftptest.cgi HTTP/1.0"
2022/03/01 08:30:20 [error] 1383#0: ffing cn*2361 directory index of "/usr/share/nginx/yourls-ffing/" is forbidden, client: 157.55.39.190, server: yourls.ffing.cn, request: "GET / HTTP/1.1", host: "yourls.ffing.cn"
2022/03/01 08:30:40 [error] 1383#0:  ffing cn *2693 open() "/usr/share/nginx/phpinfo/manager/html" failed (2: No such file or directory), client: 111.197.65.99, server: , request: "GET /manager/html HTTP/1.1", host: "49.233.25.243:81"

第一种:枚举时间戳

思路简单,使用date -d 参数里生成时间戳,去遍历日志中时间(可提前过滤出时间列)这种方法思路比较简单,但会遍历每一秒,需要消耗枚举时间,因此这种方法适合时间戳密集的日志,时间戳稀疏的不合适。

如果日志一个时间戳日志是“多行”或者时间戳日志出现“多个时间”,需要看我前面的分割日志的文章,需要对时间戳进行过滤修改,我的方法是对时间戳日志提前输出到一个临时文件,再追加一个标识符,方便识别

贴下脚本:

输入值,自行补充判断。

#!/bin/bash
read -p "请输入日志路径:" FILE
read -p "请输入两个时间段(空格分隔):" F1 F2


#获取起始时间FF1
I=0
while true
do 
	FF1=`date -d "$(echo $F1|sed 's/://') +$I second" +%H:%M:%S`
	#不能大于结束时间
	if [  $(date -d "$FF1" +%s) -lt $(date -d "$F2" +%s)  ];then
				grep "$FF1" $FILE >/dev/null 2>&1
				if [ $? -eq 0 ];then
				echo "最近起始时间节点$FF1";
				break
				fi
	else
	FF1=""
	echo "未找到起始时间节点"
	break 
	fi
	let I++
done

#获取结束时间FF2
I=0
while true
do 
	FF2=`date -d "$(echo $F2|sed 's/://') -$I second" +%H:%M:%S`
	#不能大于结束时间

	if [  $(date -d "$FF1" +%s) -lt $(date -d "$FF2" +%s)  ];then
				grep $FF2 $FILE >/dev/null 2>&1
				if [ $? -eq 0 ];then
				echo "最近结束时间节点$FF2";
				break
				fi
	else
	FF2=""
	echo "未找到结束时间节点"
	break
	fi
	let I++
done
														sed -n "/$FF1/,/$FF2/"p  $FILE

第二种:时分秒对比

这个就稍微有一点绕,需要判断时分秒,起始时间很简单,顺序过滤即可。核心在于这个结束时间,需要倒序,且结束时间不存在时,就需要从59-00倒序循环。效率很高,推荐!

分析两种结束时间状态:

第一种,过滤06:00:00至08:30:30(理想状态)
最近的结束时间戳为:08:30:20
存在相同的“时”、“分”,而“秒”只需从30秒倒序到20。
即:输入“时”匹配,“分”匹配、秒从30--20(倒序)

第二种,过滤06:00:00至08:30:00
最近的结束时间戳为:7:30:08
简单当小于8:00:00秒的,肯定时、分、秒都是前位借1,也就“时”要-1,“分”要从59--00的倒序,秒也是59--00的倒序。



范例说明:需从上面的test.log中过滤6:00:30-8:30:00之间的日志

而日志中存在5个时间戳3:00:01、5:59:05、7:00:41、7:30:08、8:30:20、8:30:40

可以肉眼分别出符合这个时间段的:7:00:41、7:30:08

也就是要找:大于等于“起始时间”最近最相近时间戳和小于等于“结束时间”最相近时间戳

最近的起始时间戳:7:00:41

最近的结束时间戳:7:30:08

read -p "请输入文件路径:" FILE
read -p "请输入两个时间段(空格分隔):" F1 F2
#获取日志中时间戳
TMPHMS=`awk  /[0-9]:[0-9][0-9]:[0-9][0-9]/'{print $2}' $FILE|sort -u`
F1H=`echo $F1|awk -F":" '{print $1}'`
F1M=`echo $F1|awk -F":" '{print $2}'`
F1S=`echo $F1|awk -F":" '{print $3}'`
#如果秒为空,则00	
if [ -z $F1S ];then F1S=00 ;fi

F2H=`echo $F2|awk -F":" '{print $1}'`
F2M=`echo $F2|awk -F":" '{print $2}'`
F2S=`echo $F2|awk -F":" '{print $3}'`									
#如果秒为空,则00									
if [ -z $F2S ];then F2S=00 ;fi

	
	#获取开始时间段
	while true
	do
			#获取小时
			for H in `seq $F1H $F2H`
			do
			echo $TMPHMS|grep $H:..:..  >/dev/null 2>&1
				if [ $? -eq 0 ];then
				

					#获取分钟
					for M in `seq -w $F1M 59`
					do
						echo $TMPHMS|grep $H:$M:..  >/dev/null 2>&1
						if [ $? -eq 0 ];then
						
							#获取秒
							for S in `seq -w $F1S 59`
							do
								echo $TMPHMS|grep $H:$M:$S  >/dev/null 2>&1
								if [ $? -eq 0 ];then
								

								FF1=$H:$M:$S
								echo "起始节点:$FF1"
								break 4
								fi
							done
						fi
					done
				fi
			done

			echo "日志中未找到起始时间段"
			exit									
	done


	#获取结束时间段
	while true
	do
			#获取小时
			for HH in `seq $F1H $F2H|tac`
			do
			echo $TMPHMS|grep $HH:..:..  >/dev/null 2>&1
				if [ $? -eq 0 ];then
						
						#当“时”不等输入值,则分=59,从59倒序
						if [ ! $HH -eq $F2H ];then F2M=59;fi
						#获取分钟
						for MM in `seq -w 00 $F2M|tac `
						do
							
							echo $TMPHMS|grep $HH:$MM:..  >/dev/null 2>&1
							if [ $? -eq 0 ];then
										
										#当“时”或“分”任意一个不等于输入值时,则秒=59,从59倒序
										if [ ! $HH -eq $F2H -o  ! $MM -eq $F2M ];then F2S=59;fi
										#获取秒
										for SS in `seq -w 00 $F2S|tac`
										do
											echo $TMPHMS|grep $HH:$MM:$SS  >/dev/null 2>&1
											if [ $? -eq 0 ];then
											

											FF2=$HH:$MM:$SS
											echo "结束节点:$FF2"
											break 4
											fi

										done
							fi

						done
				fi
			done

			echo "日志中未找到结束时间段"
			exit									
	done
sed -n "/$FF1/,/$FF2/"p  $FILE

上贴脚本是从我的日志分析脚本中截取出来的,稍微做了修改,主要讲思路,勿忘。

good good study, day day up!

发表评论

textsms
account_circle
email

linux 日志时间区间过滤(非连续时间戳)
sed过滤区间日志时,需要保障过滤的值必须存在,否则就会sed到日志结尾。 因此,当过滤时间区间日志是就需要去查找最近的时间戳。 我的这个脚本是针对一天的时间区间进行过滤(…
扫描二维码继续阅读
2022-03-30