nginx中统计uv需基于日志ip去重:先确认日志格式及真实ip字段位置(如$remote_addr或$http_x_forwarded_for),再用awk提取、sort -u去重、wc -l计数;代理场景取x-forwarded-for最左ip,并建议正则过滤和抽样验证。

在 Nginx 中统计独立访客数(UV),本质是基于日志中的客户端 IP 去重计数。Shell 脚本可以快速完成这个任务,无需启动额外服务或依赖数据库。
确认日志格式和字段位置
Nginx 默认日志格式为 combined,IP 字段通常位于每行最开头。但需先确认你实际使用的日志格式是否含真实 IP(尤其有 CDN 或反向代理时):
- 若直接暴露服务器,第一列就是客户端真实 IP
- 若前端有 Nginx、CDN(如 Cloudflare)、SLB,需检查是否记录了
X-Forwarded-For或X-Real-IP,并在日志配置中显式输出,例如:log_format main '$http_x_forwarded_for - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'; - 用
head -n 1 /var/log/nginx/access.log查看一行示例,定位 IP 所在字段
基础 UV 统计命令(单文件、默认 IP)
假设 IP 在每行第一个字段(最常见情况),执行以下命令即可:
awk '{print $1}' /var/log/nginx/access.log | sort -u | wc -l
说明:
-
awk '{print $1}'提取每行第一个字段(IP) -
sort -u排序并去重(-u保证唯一性) -
wc -l统计行数,即独立 IP 数量
注意:该方法对大日志(GB 级)较慢;若需提速,可加 sort -u -S 512M 指定内存缓存大小。
处理带代理的真实 IP(推荐场景)
当使用 $http_x_forwarded_for 记录多级代理 IP(如 203.0.113.5, 198.51.100.2)时,应取最左边的原始客户端 IP:
awk -F', ' '{print $1}' /var/log/nginx/access.log | awk '{print $1}' | sort -u | wc -l
更健壮写法(兼容空格/逗号分隔、过滤无效行):
awk '{if (NF>=1 && $1 ~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) print $1; else if ($1 ~ /,/) print $1}' /var/log/nginx/access.log | awk -F'[ ,]+' '{print $1}' | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$' | sort -u | wc -l
建议先抽样验证:awk '{print $1}' access.log | head -20 看是否符合预期。
按时间范围快速统计(如最近 1 小时)
利用日志时间戳(默认格式:10/Jan/2024:14:32:01 +0800),结合 awk 时间解析:
awk -v start=$(date -d '1 hour ago' '+%d/%b/%Y:%H:%M:%S') \
-v end=$(date '+%d/%b/%Y:%H:%M:%S') \
'$4 ~ /\[.*'"$start"'[^]]*|'"$end"'[^]]*/ {print $1}' \
/var/log/nginx/access.log | sort -u | wc -l
更可靠做法是用 sed -n '/$(date ...)/,/^$/p' 配合日志轮转策略,或先用 grep 粗筛时间再处理。











