awk分析Nginx日志

以下是一个基于 Nginx 访问日志的 AWK 逻辑组合实战示例,模拟实际工作中“多条件筛选异常请求并统计”的场景,包含基础逻辑组合、高级统计及输出格式化。

场景背景

假设我们有一份 Nginx 访问日志 access.log,格式如下(简化版,字段含义对应):

$1: 客户端IP  $4: 访问时间  $6: 请求方法  $7: 请求路径  $9: 状态码  $10: 响应大小(字节)  

示例日志内容:

192.168.1.1 - - [10/Oct/2023:10:00:00 +0800] "GET /index.html HTTP/1.1" 200 1500  
10.0.0.2 - - [10/Oct/2023:10:01:30 +0800] "POST /login HTTP/1.1" 500 0  
192.168.1.3 - - [10/Oct/2023:10:02:15 +0800] "GET /api/data HTTP/1.1" 404 100  
10.0.0.2 - - [10/Oct/2023:10:03:00 +0800] "POST /login HTTP/1.1" 500 0  
192.168.1.1 - - [10/Oct/2023:10:05:00 +0800] "GET /largefile.zip HTTP/1.1" 200 10485760  

需求目标

用 AWK 逻辑组合实现:

  1. 筛选两类“异常请求”:
    • 条件A:状态码为 500(服务器错误)且请求方法为 POST 的请求(可能是接口故障)。
    • 条件B:状态码为 200(正常)但响应大小 > 10MB(10485760 字节)的 GET 请求(可能是大文件滥用)。
  2. 分别统计两类异常的出现次数,并按 IP 分组统计。
  3. 输出格式化报告,包含总次数和 Top IP。

实现代码

#!/usr/bin/awk -f  
# 处理 Nginx 日志,筛选并统计异常请求  

# 字段对应(根据实际日志格式调整)  
# $1: IP  $6: 请求方法(如"GET")  $9: 状态码  $10: 响应大小  

# 逻辑组合筛选异常请求,并统计  
{  
  # 条件A:500错误 + POST请求(提取方法时去除引号,如"POST→POST)  
  if ($9 == 500 && substr($6, 2, length($6)-2) == "POST") {  
    typeA_total++                     # 总次数+1  
    typeA_ip[$1]++                    # 按IP统计  
  }  
  # 条件B:200正常 + GET请求 + 响应大小>10MB(10485760字节)  
  else if ($9 == 200 && substr($6, 2, length($6)-2) == "GET" && $10 > 10485760) {  
    typeB_total++                     # 总次数+1  
    typeB_ip[$1]++                    # 按IP统计  
  }  
}  

# 输出报告(END块汇总结果)  
END {  
  print "===== 异常请求统计报告 ====="  
  # 输出类型A统计  
  print "\n1. 服务器错误(500+POST):"  
  print "   总次数:", typeA_total  
  print "   主要IP分布:"  
  for (ip in typeA_ip) {  
    printf "      %-15s 出现 %d 次\n", ip, typeA_ip[ip]  
  }  

  # 输出类型B统计  
  print "\n2. 大文件请求(200+GET+>10MB):"  
  print "   总次数:", typeB_total  
  print "   主要IP分布:"  
  for (ip in typeB_ip) {  
    printf "      %-15s 出现 %d 次\n", ip, typeB_ip[ip]  
  }  
}  

执行与输出

  1. 保存脚本为 log_analysis.awk,添加执行权限:chmod +x log_analysis.awk
  2. 执行:./log_analysis.awk access.log
  3. 输出结果:
===== 异常请求统计报告 =====  

1. 服务器错误(500+POST):  
   总次数: 2  
   主要IP分布:  
      10.0.0.2        出现 2 次  

2. 大文件请求(200+GET+>10MB):  
   总次数: 1  
   主要IP分布:  
      192.168.1.1     出现 1 次  

逻辑组合解析

  1. 多条件“与”组合
    • 条件A用 $9 == 500 && 方法==POST,确保同时满足“状态码500”和“POST请求”。
    • 条件B用 $9 == 200 && 方法==GET && 大小>10MB,三重条件筛选大文件请求。
  2. 字符串处理与逻辑结合
    • 用 substr($6, 2, length($6)-2) 提取请求方法(去除日志中方法外的引号,如 "POSTPOST),避免因引号导致匹配失败。
  3. 分支逻辑(if-else)
    • 用 else if 区分两类异常,避免重复统计(同一行不会同时属于A和B)。
  4. 数组统计
    • 用关联数组 typeA_ip[$1]++ 按IP分组,实现“多维度统计”(既算总数,又看IP分布)。

实际价值

此示例可直接用于生产环境的日志监控:

  • 快速定位接口故障(500+POST)的频发IP,排查是否为恶意请求;
  • 识别大文件滥用(200+GET+大尺寸)的IP,限制其带宽或访问权限;
  • 通过逻辑组合灵活扩展规则(如添加时间范围 $4 ~ /10:00:00/ 筛选特定时段异常)。
此条目发表在linux文章分类目录。将固定链接加入收藏夹。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注