以下是一个基于 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 逻辑组合实现:
- 筛选两类“异常请求”:
- 条件A:状态码为 500(服务器错误)且请求方法为 POST 的请求(可能是接口故障)。
- 条件B:状态码为 200(正常)但响应大小 > 10MB(10485760 字节)的 GET 请求(可能是大文件滥用)。
- 分别统计两类异常的出现次数,并按 IP 分组统计。
- 输出格式化报告,包含总次数和 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]
}
}
执行与输出
- 保存脚本为
log_analysis.awk
,添加执行权限:chmod +x log_analysis.awk
- 执行:
./log_analysis.awk access.log
- 输出结果:
===== 异常请求统计报告 =====
1. 服务器错误(500+POST):
总次数: 2
主要IP分布:
10.0.0.2 出现 2 次
2. 大文件请求(200+GET+>10MB):
总次数: 1
主要IP分布:
192.168.1.1 出现 1 次
逻辑组合解析
- 多条件“与”组合:
- 条件A用
$9 == 500 && 方法==POST
,确保同时满足“状态码500”和“POST请求”。 - 条件B用
$9 == 200 && 方法==GET && 大小>10MB
,三重条件筛选大文件请求。
- 条件A用
- 字符串处理与逻辑结合:
- 用
substr($6, 2, length($6)-2)
提取请求方法(去除日志中方法外的引号,如"POST
→POST
),避免因引号导致匹配失败。
- 用
- 分支逻辑(if-else):
- 用
else if
区分两类异常,避免重复统计(同一行不会同时属于A和B)。
- 用
- 数组统计:
- 用关联数组
typeA_ip[$1]++
按IP分组,实现“多维度统计”(既算总数,又看IP分布)。
- 用关联数组
实际价值
此示例可直接用于生产环境的日志监控:
- 快速定位接口故障(500+POST)的频发IP,排查是否为恶意请求;
- 识别大文件滥用(200+GET+大尺寸)的IP,限制其带宽或访问权限;
- 通过逻辑组合灵活扩展规则(如添加时间范围
$4 ~ /10:00:00/
筛选特定时段异常)。