MST

星途 面试题库

面试题:Bash日期时间处理结合系统日志分析

假设系统日志文件(/var/log/syslog)中记录了每条日志的时间戳(格式如:Jan 10 14:23:56),现在需要统计过去一周内(按自然周,从上周日0点到上周六23:59:59)出现频率最高的10条日志信息。请用Bash脚本实现,要求详细注释每一步的操作逻辑,并且说明如何处理时间跨度计算和日志信息统计。
46.7万 热度难度
编程语言Bash

知识考点

AI 面试

面试题答案

一键面试
#!/bin/bash

# 获取当前日期
current_date=$(date +%Y-%m-%d)

# 计算上周日的日期,-d '-7 days' 表示往前推7天,'+%Y-%m-%d' 是格式化输出
last_sunday=$(date -d "$current_date -7 days -$(date -d "$current_date -7 days" +%w) days" +%Y-%m-%d)

# 计算上周六的日期,-d表示日期运算,这里是在上周日的基础上加上6天
last_saturday=$(date -d "$last_sunday +6 days" +%Y-%m-%d)

# 将日期转换为系统日志中的时间戳格式,date -d 用于解析日期,'+%b %d' 是格式化为日志中的月和日
last_sunday_formatted=$(date -d "$last_sunday" +%b\ %d)
last_saturday_formatted=$(date -d "$last_saturday" +%b\ %d)

# 使用awk进行筛选和统计,以下是awk脚本部分
# BEGIN块在处理文件前执行,初始化计数器数组
awk -v start_date="$last_sunday_formatted" -v end_date="$last_saturday_formatted" '
BEGIN {
    FS = " "
}
# 匹配时间范围
$1 " " $2 >= start_date && $1 " " $2 <= end_date {
    # 拼接日志信息,从第3个字段开始到最后一个字段
    log_message = ""
    for (i = 3; i <= NF; i++) {
        log_message = log_message " " $i
    }
    # 去除开头的空格
    sub(/^ /, "", log_message)
    # 统计日志信息的出现次数
    count[log_message]++
}
END {
    # 遍历计数器数组,输出出现次数和日志信息
    for (message in count) {
        print count[message] " " message
    }
}' /var/log/syslog |
# 按出现次数进行降序排序
sort -nr |
# 取前10条记录
head -n 10

时间跨度计算

  1. 首先获取当前日期 current_date,使用 date +%Y-%m-%d 格式化输出当前日期。
  2. 计算上周日的日期 last_sunday,通过 -d '-7 days' 往前推7天,再减去当前日期往前推7天后是周几的天数(date -d "$current_date -7 days" +%w),就得到上周日的日期,并格式化为 %Y-%m-%d
  3. 计算上周六的日期 last_saturday,通过在上周日的日期基础上加上6天得到。
  4. 将上周日和上周六的日期转换为系统日志中的时间戳格式 last_sunday_formattedlast_saturday_formatted,使用 date -d 解析日期并格式化为 %b %d,即日志中的月和日的格式。

日志信息统计

  1. 使用 awk 工具处理日志文件 /var/log/syslog
  2. BEGIN 块中,设置字段分隔符 FS 为空格,这样可以按空格分割每一行日志。
  3. 通过条件 $1 " " $2 >= start_date && $1 " " $2 <= end_date 匹配时间范围内的日志,$1 是日志中的月份,$2 是日期。
  4. 拼接日志信息,从第3个字段开始到最后一个字段,去除开头的空格,并存入 log_message 变量。
  5. 使用关联数组 count 统计每条日志信息的出现次数。
  6. END 块中,遍历 count 数组,输出每条日志信息的出现次数和日志信息本身。
  7. 使用 sort -nr 对输出结果按出现次数进行降序排序。
  8. 使用 head -n 10 取出现频率最高的前10条日志信息。