8.5---筛选给定时间范围内的日志

文章目录

  • 时间戳及当地时间的转换:
    • 1、概述:
    • 2、时间两种表示方法:
  • 简单实例:
  • 进阶实例:
    • 拓展知识:
  • 操作过程:

时间戳及当地时间的转换:

1、概述:

新纪元(epoch):UNIX及Linux的时间系统是由「新纪元时间」Epoch开始计算起,单位为秒,Epoch则是指定为1970年一月一日凌晨零点零分零秒,格林威治时间。

夏时制(Daylight Saving Time:DST):又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。
一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。

时区:世界按照经度被划分为24个时区;

2、时间两种表示方法:

时间戳:从新纪元开始到当前时间的秒数。
当地年月日时间:组成部分为 年、月、日、时、分、秒、是否是夏时制、当地时区。

简单实例:

由于grep/sed/awk用正则去筛选日志时,如果要精确到小时、分钟、秒,则非常难以实现。

因此,awk提供了**mktime()函数**,它可以将时间转换成epoch时间值。

mktime函数创建指定时间,转化为时间戳
特别注意中间必须以空格分割!!!
mktime(“2018 09 09 12 12 20”)

#将 2019-11-10 03:42:40转换成epoch为1970-01-01 00:00:00

[root@localhost ~]# awk  'BEGIN{print mktime("2019 11 10 03 42 40")}'
1573375360

上代码,提取日志中的时间字符串部分,再将他们的年、月、日、时、分、秒都取出来,然后放入mktime()构建成对应的epoch值。因为epoch值是数值,所以可以比较大小,从而决定时间的大小。

进阶实例:

下面将strptime2()实现的是将
27/Jul/2023:18:36:30+0800 格式的字符串转换成 epoch 值,然后和 which_time 比较大小,既可以筛选出精确到秒的日志。

BEGIN{
  # 要筛选什么时间的日志,将其时间构建成epoch值
  which_time = mktime("2023 07 27 18 36 30")
}

{
  # 取出日志中的日期时间字符串部分
  match($0,"^.*\\[(.*)\\].*",arr)

  # 将日期时间字符串转换为epoch值
  tmp_time = strptime2(arr[1])

  # 通过比较epoch值来比较时间大小
  if(tmp_time > which_time){
    print
  }
}

# 构建的时间字符串格式为:"27/Jul/2023:18:36:30+0800"
function strptime2(str,dt_str,arr,Y,M,D,H,m,S) {
  dt_str = gensub("[/:+]"," ","g",str)
  # dt_sr = "27 Jul 2023 18 36 30 08 00"
  split(dt_str,arr," ")
  Y=arr[3]
  M=mon_map(arr[2])
  D=arr[1]
  H=arr[4]
  m=arr[5]
  S=arr[6]
  return mktime(sprintf("%s %s %s %s %s %s",Y,M,D,H,m,S))
} 
function mon_map(str,mons){
  mons["Jan"]=01
  mons["Feb"]=02
  mons["Mar"]=03
  mons["Apr"]=04
  mons["May"]=05
  mons["Jun"]=06
  mons["Jul"]=07
  mons["Aug"]=08
  mons["Sep"]=09
  mons["Oct"]=10
  mons["Nov"]=11
  mons["Dec"]=12
  return mons[str]
}

上代码:(理解过程)
首先通过 mktime函数将日期时间信息转换为 epoch 值时间戳,这样就可以直接比较时间了;
其次使用 match函数匹配正则表达式,取出日志中的日期时间字符串部分;
然后通过 strptime2()函数转为 epoch值。函数内部通过 gensub函数匹配正则,将 “/ : +”替换成空格,这样 mktime函数就可以转换了,(同时也可以使用 split函数,该函数也是将字符串按照空格分隔),然后保存在 arr数组,而后给 YMDHmS赋值,mon_map函数,将月份的英文转换为数字,最后返回 mktime函数处理后的 epoch值;
最后 if语句比较时间,如果获取时间>规定的时间就打印出来;
从而得出可以筛选出精确到秒的日志。

拓展知识:

gensub 函数:

image.png
gensub(regexp,replacement,how[,target])
1. 这个函数可以灵活控制去替换第几个被匹配到的字符;
2. how可以填充g或G表示全局匹配,也可以填充n表示替换匹配到的第n个;
3. gensub函数不会对原来的内容直接替换,而是需要将函数的结果赋值给变量,然后再对变量输出当需要使用时,需要对gensub函数进行赋值a=gensub(regexp,replacement,how[,target]),然后再print a;
4. gensub函数支持使用括号来标记正则表达式regexp,然后在replacement使用"\N"来反向引用括号内的内容;

  1. 当replacement中有&符号,表示对regexp的反向引用,用来拼接使用;

(如果需要使用&这个字符,需要用两个转义符转义\)

strptime 函数:

原理:分析表示根据格式的时间字符串。
格式参数默认为:“%a %b %d %H:%M:%S %Y”
指令:
%a - 简写的星期几;
%b - 缩写的月份名称;
%H - 小时,使用24小时制;
%I - 小时,使用12小时制
%M - 分钟;
%S - 秒;
%Y - 今年,包括世纪;
%Z or %z - 时区或名称或缩写

操作过程:

1、首先创建 access.log 日志文件;选定好时间,如下所示

image.png
8.5---筛选给定时间范围内的日志_第1张图片

2、其次再编写筛选规则 3.awk 文件;如下

8.5---筛选给定时间范围内的日志_第2张图片

3、使用 awk 命令 -f 选项 从脚本文件中读取 access.log日志文件,从而进行筛选;

8.5---筛选给定时间范围内的日志_第3张图片

4、对比,筛选前后利用awk 抓取了时间段部分进行对比;

筛选前:
8.5---筛选给定时间范围内的日志_第4张图片
筛选后:
8.5---筛选给定时间范围内的日志_第5张图片

经过对比表明,已经成功筛选出 指定时间 27/Jul/2023:18:36:30+0800 以上的日志,实验成功!;



感谢点赞支持,小Rong会继续努力!!!

你可能感兴趣的:(开发语言,运维)