在Nginx中统计Top 10真实客户端IP需确保log_format包含$http_x_forwarded_for或$http_x_real_ip,再用awk、cut、sort等命令提取首IP并排序;若含CDN/代理,须处理X-Forwarded-For多级IP及IPv6、空行等异常。

在 Nginx 中统计访问日志中的 Top 10 访问源 IP,核心是解析 access.log 文件,并按 IP 出现次数排序。需要注意的是:如果服务器前有 CDN、反向代理(如负载均衡器),$remote_addr 可能是代理 IP,真实 IP 通常存在 X-Forwarded-For 或 X-Real-IP 请求头中——日志格式必须已记录该字段,否则无法准确统计。
确认日志中记录了真实客户端 IP
Nginx 默认日志使用 $remote_addr,它只反映直连客户端(可能是代理)。要统计真实用户 IP,需确保 log_format 中包含 $http_x_forwarded_for 或 $http_x_real_ip,例如:
log_format main '$http_x_forwarded_for - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
若未配置,请先修改 nginx.conf 并重载配置(nginx -s reload),再采集新日志数据。
用 shell 命令快速提取 Top 10 源 IP
假设日志中真实 IP 记录在第一列(如 X-Forwarded-For 字段),且每行一个请求,可使用以下命令:
-
提取首 IP(处理多级代理):X-Forwarded-For 可能含多个 IP(如
1.1.1.1, 2.2.2.2, 3.3.3.3),取最左边的才是原始客户端 IP:awk '{print $1}' /var/log/nginx/access.log | cut -d',' -f1 | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' | sort | uniq -c | sort -nr | head -10 -
过滤空行和无效 IP:加上
grep -v '^$' | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'提高准确性 -
实时跟踪新增请求:用
tail -f配合awk动态统计(适合调试):tail -f /var/log/nginx/access.log | awk '{print $1}' | cut -d',' -f1 | sort | uniq -c | sort -nr | head -10(注意:此方式不累计,仅显示当前窗口内频次)
处理 IPv6 和异常格式
若日志含 IPv6 地址或混合格式(如带端口、方括号),需调整提取逻辑:
- IPv6 示例:
2001:db8::1或[2001:db8::1],可用sed 's/^\[//; s/\]$//'去括号 - 避免把
-(表示缺失)或localhost当作 IP:加grep -v '^-$' | grep -v '^localhost$' - 更健壮的 IP 匹配(支持 IPv4/IPv6):
grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}|([a-f0-9:]+:+)+[a-f0-9]+' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
进阶:用脚本或工具长期监控
手动命令适合临时分析;生产环境建议:
- 写成定时脚本(如每小时执行),结果存入文件或推送到监控系统
- 用
goaccess(支持实时可视化):goaccess /var/log/nginx/access.log --log-format=COMBINED --ip-field=1 --real-ip-field=1(需配合正确 log_format) - 接入 ELK(Elasticsearch + Logstash + Kibana)或 Grafana Loki,实现聚合、告警与图表展示











