关键在于统计准确性,需准确定位ip字段、处理代理干扰、过滤无效请求,并用awk数组单次扫描提升性能。

直接用 awk 统计日志中访问频次,关键不是“能不能跑”,而是“统计得准不准”——IP字段位置、代理干扰、无效请求、性能瓶颈,每一步都容易出错。
确认 IP 字段在日志中的实际位置
默认认为 $1 是客户端 IP,但只适用于标准格式(如 Apache 默认、Nginx 未启用 real_ip 模块)。如果日志启用了 log_format 并记录了 $http_x_forwarded_for,真实 IP 往往藏在引号包裹的字段里,比如:
-
"203.0.113.5, 192.168.1.100, 198.51.100.7"—— 要取最左的203.0.113.5,不是最后一个 - 不能写
awk '{print $NF}',那会拿到负载均衡器地址 - 正确做法是定位含 X-Forwarded-For 的字段(通常是
$2或$4),再切分取首项:awk '{if ($2 ~ /^"/) {gsub(/^"|"$/, "", $2); n=split($2,a,/,\s*/); print a[1]} else {print $1}}'
过滤掉干扰行,避免统计失真
空行、健康检查、错误响应、爬虫请求混在日志里,会拉低有效访问占比。加条件筛掉它们:
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
- 只处理以 IPv4 开头的行:
/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ - 排除常见干扰路径:
!/\/healthz|\/favicon\.ico|\/robots\.txt/ - 跳过 4xx/5xx 响应(可选):
$9 !~ /^4|^5/(需确认$9是状态码列) - 组合示例:
awk '/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ && !/healthz|404|403/ {print $1}' access.log
用数组单次扫描,兼顾速度与内存
对大日志(>500MB),链式管道 sort | uniq -c | sort 会读三遍磁盘,慢且耗资源。改用 awk 内部数组一次扫完:
awk '{ip[$1]++} END {for (i in ip) print ip[i], i}' access.log | sort -nr- 优势:只读一遍文件;自动去重计数;逻辑清晰
- 注意:内存占用取决于唯一 IP 数量;千万级 IP 时慎用;排序仍需外部
sort -nr - 想限制输出前 N 名?加管道:
| head -20
按需扩展:查 TOP N、筛高频、导出结果
统计只是起点,后续操作很常用:
- 取访问最多的前 10 个 IP:
awk '{a[$1]++} END {for(i in a) print a[i],i}' access.log | sort -nr | head -10 - 只看出现超 100 次的 IP:
awk '{a[$1]++} END {for(i in a) if(a[i]>100) print i,a[i]}' access.log - 导出为 CSV 格式便于分析:
awk '{a[$1]++} END {for(i in a) print i "," a[i]}' access.log > ip_count.csv










