🚀 第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/监控工具。