关键在于精准匹配、快速过滤与稳定聚合:先确认ip字段位置,再按高频访问、高错误率或扫描特征筛选,最后优化大日志处理效率。

用 awk 分析 Nginx 日志提取异常 IP,关键不在“写得复杂”,而在“匹配准、过滤快、聚合稳”。核心思路是:先定位日志格式(尤其是 IP 字段位置),再按异常特征(如高频 404/500、大量 POST、短时高并发)筛选,最后去重或排序统计。下面分三步给出实用脚本结构和优化要点。
一、确认 Nginx 日志字段顺序,精准取 IP
Nginx 默认 access_log 格式中,客户端 IP 通常在第一列(但若启用了反向代理且未配置 $remote_addr 或 $http_x_forwarded_for,可能需调整)。先用 head 看一行确认:
常见格式示例:
192.168.1.100 - - [10/Jan/2024:08:23:45 +0000] "GET /api/v1/user HTTP/1.1" 200 1234 "https://example.com" "Mozilla/5.0..."
此时 IP 在第 1 字段,awk 中用 $1 即可。若含多层代理,且日志中记录了 X-Forwarded-For,则需解析该字段(如 $NF 或正则提取最左非内网 IP),不建议硬写 $2 或 $3 —— 易错。
二、按典型异常特征编写单行 awk 提取逻辑
以下命令均以“每分钟内请求 ≥100 次”或“4xx/5xx 错误率 >30%”为阈值示例,可依实际调低/调高:
-
高频访问 IP(单位时间请求数):
awk '{ip[$1]++} END {for (i in ip) if (ip[i] >= 100) print i, ip[i]}' /var/log/nginx/access.log | sort -k2nr -
高错误率 IP(4xx/5xx 占比):
awk '$9 ~ /^4|5/ {err[$1]++; total[$1]++} $9 !~ /^4|5/ {total[$1]++} END {for (i in total) if (err[i] && err[i]/total[i] > 0.3) print i, err[i], total[i]}' /var/log/nginx/access.log -
疑似扫描行为(大量 404 + 非常规路径):
awk '$9 == 404 && ($7 ~ /phpmyadmin|wp-admin|\.env|\.git/ || length($7) > 200) {ip[$1]++} END {for (i in ip) if (ip[i] >= 5) print i, ip[i]}' /var/log/nginx/access.log
三、提升效率的关键细节
大日志文件(>1GB)直接全量 awk 易卡顿,建议结合时间范围与系统工具加速:
- 用
zcat或gunzip -c直接处理压缩日志,避免解压到磁盘 - 用
sed -n '/2024:08:2[0-9]/p'或awk '/\[10\/Jan.*:08:[2-3][0-9]:[0-5][0-9]/'先截取目标时间段,再进 awk - 避免在 awk 中用
system()或循环调用外部命令;统计类任务优先用关联数组,而非管道反复 grep - 若需长期监控,把常用逻辑封装成函数式 awk 脚本(
#!/usr/bin/awk -f),支持传参如-v threshold=50
真正高效的脚本不是功能最多,而是能快速响应变化——比如换日志格式只需改一个字段号,加新规则只增几行条件。从明确目标 IP 字段开始,聚焦 1–2 个高价值异常模式,再逐步叠加,比一上来写“全能分析器”更可靠。











