🚀 第09章 · 日志与访问统计

access_log/error_log 分析

日志与访问统计

这一章讲 Nginx 日志:access log 记录谁访问了你、error log 记录 Nginx 自身的错误,以及怎么从日志里做访问统计、找 404/慢请求。本机把每个站点的日志分开存(如 /var/log/nginx/learn.access.log),排查和统计都方便。

两大类日志

日志 默认路径 记录内容
access log(访问日志) /var/log/nginx/access.log,或站点自己指定 谁、何时、请求了什么、返回什么状态、多大、多久
error log(错误日志) /var/log/nginx/error.log Nginx 自身/上游的错误(emerg/error/notice/...)

提示 | 默认 access 只写一个全局文件;生产建议每个站点独立日志,并在反代时就写好。本机就是这样:每个 server 块里 access_log /var/log/nginx/<域>.access.log;。

配置日志

# 定义日志格式(可选,自己定制字段)
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" "$http_user_agent"';

server {
    server_name learn.bangdream.xyz;
    access_log /var/log/nginx/learn.access.log main;
    error_log  /var/log/nginx/learn.error.log;
}

常用变量:

变量 含义
$remote_addr 客户端 IP
$request 请求行(方法、URI、协议)
$status HTTP 状态码
$body_bytes_sent 响应体大小
$http_referer 来源页
$http_user_agent 浏览器/UA
$time_local / $request_time 时间 / 请求耗时

查看日志

# 实时跟随(看访问)
sudo tail -f /var/log/nginx/learn.access.log
# 看错误日志
sudo tail -n 50 /var/log/nginx/learn.error.log
# 最近 10 分钟内的访问
grep "$(date -d '10 minutes ago' '+%d/%b/%Y:%H')" /var/log/nginx/learn.access.log | tail

常见统计命令

统计访问量:

# 一共多少条(去掉空行)
wc -l /var/log/nginx/learn.access.log
# 每小时成功/失败等
awk '{print $9}' /var/log/nginx/learn.access.log | sort | uniq -c | sort -rn

统计访问最多的 IP 前 10:

awk '{print $1}' /var/log/nginx/learn.access.log | sort | uniq -c | sort -rn | head -10

统计返回 404 的请求:

grep ' 404 ' /var/log/nginx/learn.access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head

按 URL 统计热门页面:

awk '{print $7}' /var/log/nginx/learn.access.log | sort | uniq -c | sort -rn | head -20

定位慢请求 / 上游超时

如果你定义了 $request_time 等变量,可按耗时排序:

# 找到耗时最长的请求(假设格式里第 N 列是时间,读一下 log_format)
awk '{print $NF, $0}' /var/log/nginx/learn.access.log | sort -rn | head

更多时候看 error log 里与 upstream 相关的错误:

sudo grep -iE "timeout|upstream|502|504" /var/log/nginx/learn.error.log | tail -20
error log 常见行 含义
upstream timed out (110: Operation timed out) 后端响应太慢超时
connect() failed (111: Connection refused) 后端没监听/挂了
no live upstreams 所有后端都不可用
open() "/var/www/learn/..." failed (13: Permission denied) 权限不足

日志轮转(logrotate)

日志会无限增长,务必轮转(参考《Linux 系统运维 · 日志管理》)。Nginx 通常有自带规则 /etc/logrotate.d/nginx。设置好之后,用这个命令手动触发或强制轮转并重载:

sudo logrotate -d /etc/logrotate.d/nginx   # 干跑模拟
sudo logrotate -f /etc/logrotate.d/nginx   # 强制轮转

注意 | Nginx 日志在轮转后若 Nginx 仍在写打开的文件句柄,需要 nginx -s reopen(或重启)让日志重新写新文件。很多 logrotate 规则里会在 postrotate 里带上 nginx -s reopen。

小结:排查异常流量/爬虫/攻击

  • 刷量、扫端口 → 看访问最多的 IP 与返回码。
  • 防盗链 → 看 referer 分布:awk '{print $11}'(取决于格式)。
  • 攻击扫描 → 看大量 404/403 及可疑 UA。

相关命令

  • tail -f、grep、awk、sort | uniq -c | sort -rn 做基础统计。
  • logrotate 轮转;nginx -s reopen 重新打开日志。
  • 进阶用 goaccess <日志>(终端可交互的实时日志分析)或 nginx access.log 喂给 ELK/监控工具。