利用 Nginx 日志进行流量监控
一 核心指标与日志字段
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time '
'$upstream_connect_time $upstream_header_time';
access_log /var/log/nginx/access.log main;
说明:上述字段覆盖“带宽/流量”“时延”“来源”三大类监控需求,便于后续聚合与告警。二 快速命令行统计
# 当天总请求数
wc -l < /var/log/nginx/access.log
# 当天总出站流量(字节)
awk '{sum+=$10} END {print sum}' /var/log/nginx/access.log
# 换算为 MB
awk '{sum+=$10} END {printf "%.2f MB\n", sum/1024/1024}' /var/log/nginx/access.log
# 最近 60 分钟总流量
awk -v d1="$(date -d '-60 minutes' +'%d/%b/%Y:%H:%M:%S')" \
-v d2="$(date +'%d/%b/%Y:%H:%M:%S')" \
'$4 >= "["d1 && $4 <= "["d2 {sum+=$10} END {printf "%.2f MB\n", sum/1024/1024}' \
/var/log/nginx/access.log
# 按小时汇总当天流量
awk -F: '{h=$2; sum[h]+=$10} END {for (i in sum) printf "%s: %.2f MB\n", i, sum[i]/1024/1024}' \
/var/log/nginx/access.log
# Top 10 URL 流量
awk '{bytes[$7]+=$10} END {for (u in bytes) printf "%.2f MB %s\n", bytes[u]/1024/1024, u}' \
/var/log/nginx/access.log | sort -nr | head
# 按状态码分布
awk '{code[$9]++} END {for (c in code) printf "%s: %d\n", c, code[c]}' \
/var/log/nginx/access.log | sort -nr
# Top 10 来源 IP 流量
awk '{ip[$1]+=$10} END {for (i in ip) printf "%.2f MB %s\n", ip[i]/1024/1024, i}' \
/var/log/nginx/access.log | sort -nr | head
三 可视化与实时监控
# 控制台实时
goaccess /var/log/nginx/access.log --log-format=COMBINED
# 生成 HTML 报告(含带宽/流量)
goaccess /var/log/nginx/access.log -o /var/www/report.html --log-format=COMBINED
# 实时 HTML(需浏览器自动刷新)
goaccess /var/log/nginx/access.log \
--log-format=COMBINED --real-time-html --port=7890 \
-o /var/www/realtime.html
提示:可结合 –ignore-crawlers 过滤爬虫,或用 –geoip-database 做地域分布。四 阈值告警与自动处置
#!/usr/bin/env bash
LOG=/var/log/nginx/access.log
LIMIT_MB=1024 # 每小时阈值(MB)
NOW=$(date +%d/%b/%Y:%H:00:00)
PREV=$(date -d '1 hour ago' +%d/%b/%Y:%H:00:00)
usage=$(awk -v d1="[$PREV" -v d2="[$NOW" \
'$4 >= d1 && $4 < d2 {sum+=$10} END {print int(sum/1024/1024)}' "$LOG")
if [ "$usage" -gt "$LIMIT_MB" ]; then
echo "$(date) 流量告警: 最近1小时 ${usage}MB > ${LIMIT_MB}MB" \
| mail -s "Nginx 流量告警" admin@example.com
# 可选:触发限流/封禁
# iptables -A INPUT -s <IP> -j DROP
fi
五 日志管理与口径一致性
# 手动切割
mv /var/log/nginx/access.log /var/log/nginx/access_$(date +%Y%m%d).log
systemctl reload nginx
# 自动清理 30 天前日志
find /var/log/nginx -name "*.log" -mtime +30 -exec gzip {} \;