Nginx配置访问日志,日志切割和分析
前言
Nginx 默认就会记录访问日志,放在 /var/log/nginx/ 目录下。但日志每天都在涨,时间长了占满磁盘,还不好查。本文就讲一下 Nginx 日志配置、切割和分析方法。
默认日志位置
Nginx 默认日志文件:
/var/log/nginx/
├── access.log # 访问日志
└── error.log # 错误日志
日志格式
Nginx 默认的日志格式叫 combined,记录这些信息:
- 客户端 IP
- 访问时间
- 请求方法和路径
- 状态码
- 响应大小
- Referer
- User-Agent
自定义日志格式
在 nginx.conf 的 http 块里可以自定义日志格式:
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
}
常用变量
| 变量 | 说明 |
|---|---|
$remote_addr |
客户端 IP |
$time_local |
本地时间 |
$request |
请求行 |
$status |
状态码 |
$body_bytes_sent |
响应大小 |
$http_referer |
来源页面 |
$http_user_agent |
浏览器信息 |
$request_time |
请求耗时 |
按站点分日志
不同站点的日志分开存,方便排查问题:
server {
listen 80;
server_name www.example.com;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}
日志切割
用 logrotate 切割
CentOS7 装完 Nginx 就自动配了 logrotate,不用管。配置文件在:
/etc/logrotate.d/nginx
内容大概是:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
notifempty
create 0640 nginx adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
意思是:
- 每天切割一次
- 保留 14 天
- 压缩旧日志
- 空日志不切割
手动测试切割
logrotate -f /etc/logrotate.d/nginx
日志分析常用命令
查看访问量前 10 的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
查看访问量前 10 的页面
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
查看状态码统计
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
查看爬虫访问
grep 'Googlebot' /var/log/nginx/access.log
查看某个 IP 的访问
grep '192.168.1.1' /var/log/nginx/access.log
常见坑
坑1:日志越来越大占满磁盘
日志不切割,时间长了把磁盘占满。
解决: 确认 logrotate 在运行:
cat /var/lib/logrotate.status
或者手动执行一次:
logrotate -f /etc/logrotate.d/nginx
坑2:日志里 IP 不对
日志里全是 127.0.0.1,不是真实用户 IP。
原因: Nginx 前面还有一层代理(比如 CDN),或者配了反向代理。
解决: 用 $http_x_forwarded_for 代替 $remote_addr:
log_format main '$http_x_forwarded_for - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent"';
坑3:日志级别太高
错误日志里全是 notice,没用还占空间。
解决: 把错误日志级别调高一点:
error_log /var/log/nginx/error.log warn;
可选级别:debug、info、notice、warn、error、crit。
总结
Nginx 日志的常用操作:
| 操作 | 命令 |
|---|---|
| 看访问日志 | tail -f /var/log/nginx/access.log |
| 看错误日志 | tail -f /var/log/nginx/error.log |
| 统计 IP | awk '{print $1}' access.log \| sort \| uniq -c |
| 统计页面 | awk '{print $7}' access.log \| sort \| uniq -c |
| 手动切割 | logrotate -f /etc/logrotate.d/nginx |
日志是排查问题的第一手资料,学会看日志比什么都重要。
遇到问题加QQ23979811 协助处理