📑 文章章节大纲 (点击平滑直达)
一、AWK 关联数组核心原理
在 AWK 中,所有数组在底层均为关联数组(Associative Array),类似于 Python 的字典或 JSON 的键值对(Key-Value)。其数组下标不仅支持数字索引,还可以是任意字符串。
- 语法结构:
array[key] = value - 频次累计经典范式:
a[$1]++
以每行第一列($1)作为 Key,每扫描到一条记录自动将对应计数加 1。AWK 会将未初始化的变量/元素默认置为 0,因此能极其优雅地实现行级去重与频次累加。
[!TIP] 性能与内存建议:对于数千万行的超大规模 Nginx 访问日志,
awk '{print $1}' log | sort | uniq -c | sort -nr的外部管道模式会借助磁盘临时排序,比单纯在单个 AWK 进程中维护超大哈希字典占用内存更加平稳。而在中小规模或实时排查时,纯 AWK 内部统计则更为快速直接。
二、Nginx 典型访问日志字段速查
进行 AWK 提取前,需根据具体的 Nginx 配置文件(nginx.conf)确认 log_format 字段位置。以下为标准通用日志格式对照:
$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"
| 字段序号 | 对应变量 | 含义说明 | 典型示例 |
|---|---|---|---|
$1 |
$remote_addr |
客户端访问 IP | 192.168.1.100 |
$4 |
$time_local |
访问时间(含方括号) | [24/Sep/2026:10:00:00 |
$7 |
$request 拆分 |
请求 URI 路径 | /api/v1/user/login |
$9 |
$status |
HTTP 响应状态码 | 200, 404, 502 |
$10 |
$body_bytes_sent |
发送给客户端的响应字节数 | 2048 |
三、生产排障与高频访问实战案例
1. 统计访问频次最高的 Top 10 IP
快速定位最密集的访问来源,判断是否存在单 IP 异常刷量:
# 方案 1:AWK 内部字典累加与管道排序输出
awk '{a[$1]++} END {for(i in a) print a[i], i | "sort -k1 -nr | head -n10"}' access.log
# 方案 2:经典 Unix 管道组合(易于快速敲出)
awk '{print $1}' access.log | sort | uniq -c | sort -k1 -nr | head -n10
2. 统计访问次数超阈值(> 100 次)的可疑 IP
过滤出可能需要加入防火墙或 iptables 黑名单的源 IP:
awk '{a[$1]++} END {for(i in a) {if(a[i] > 100) print i, a[i]}}' access.log | sort -k2 -nr
3. 统计访问量最高的热门 URI 接口(Top 10)
分析业务流量主力接口或高并发热点路径:
# 提取 $7 即请求的 URI 部分(去除 HTTP 协议版本)
awk '{a[$7]++} END {for(i in a) print a[i], i | "sort -k1 -nr | head -n10"}' access.log
4. 统计消耗带宽流量最大的 URI(流量 Top 10)
排查引发带宽跑满的大文件下载或静态资源泄漏:
# 累加每个 URI 消耗的响应字节数 $10
awk '{size[$7] += $10} END {for(i in size) print size[i], i | "sort -k1 -nr | head -n10"}' access.log
5. 统计全站 HTTP 响应状态码分布
全面评估当前站点服务的健康度与异常响应比例:
awk '{status[$9]++} END {for(s in status) print s, status[s]}' access.log | sort -k2 -nr
6. 统计产生 404 状态码最多的源 IP(探测/爬虫分析)
定位在全站进行敏感目录暴力扫描或漏洞探测的爬虫与恶意攻击源:
awk '$9 == "404" {a[$1]++} END {for(ip in a) print a[ip], ip | "sort -k1 -nr | head -n10"}' access.log
[!WARNING] 引号与转义避坑:如果 Nginx 配置了自定义复杂的日志格式(例如请求头含特殊转义或反向代理双重 IP),建议先执行
head -n1 access.log配合awk '{for(i=1;i<=NF;i++) print i, $i}'快速校验字段序号,确保统计列完全对齐。