Linux日志过大占满磁盘,logrotate日志切割配置
前言
网站跑久了,Nginx、MySQL、PHP-FPM的日志几个G地涨,df -h一看磁盘被日志占满,服务直接报错。手动删不是长久之计,logrotate 是Linux自带的日志切割工具,按天/按大小自动切分并保留指定份数,配一次永久省心。
一、logrotate工作原理
logrotate本身靠系统定时任务(/etc/cron.daily/logrotate)每天跑一次,读取配置:
- 全局配置:
/etc/logrotate.conf - 自定义配置目录:
/etc/logrotate.d/
我们一般在/etc/logrotate.d/下为某个服务单独写配置。
二、以Nginx日志为例配置
新建 /etc/logrotate.d/nginx:
/var/log/nginx/*.log {
daily # 按天切割
missingok # 日志不存在不报错
rotate 14 # 保留14份历史
compress # 切割后gzip压缩
delaycompress # 延迟一次再压缩,避免影响正在写的文件
notifempty # 空日志不切割
create 0644 nginx nginx # 新建日志文件属主权限
sharedscripts # 多个日志只执行一次postrotate
postrotate
if [ -f /run/nginx.pid ]; then
kill -USR1 `cat /run/nginx.pid`
fi
endscript
}
关键点:切割后要给Nginx发USR1信号,让它重新打开日志文件,否则还会往旧文件写。
三、按大小切割(不限时间)
如果日志涨得快,按大小更合理:
/var/log/nginx/error.log {
size 100M # 超过100M切
rotate 10
compress
missingok
notifempty
create 0644 nginx nginx
postrotate
kill -USR1 `cat /run/nginx.pid`
endscript
}
四、测试与立即执行
不等到定时,手动试运行(调试用 -d 打印过程不真正执行):
# 调试,看会做什么
logrotate -d /etc/logrotate.d/nginx
# 强制立即切割一次
logrotate -f /etc/logrotate.d/nginx
切割后原日志变成 xxx.log-20261021,隔天再压成 .gz。
五、常见坑
- 切割后服务还往旧文件写:缺postrotate里的
kill -USR1,或pid路径写错,导致旧文件越来越大; - 直接rm删正在写的日志:空间没释放,要
> 文件清空或重启服务; - compress和delaycompress一起用仍报错:第一次切出的文件先不压,第二次才压,别误以为没生效;
- 日志目录属主不对:create指定的用户组要真实存在,否则新建文件失败;
- cron没跑:确认
crond服务开机自启,否则logrotate永远不触发。
总结
在 /etc/logrotate.d/ 为每个大日志写一份切割规则,配好daily/size、rotate份数和postrotate信号重开日志,logrotate -f 验证一次,磁盘就不会再被单个日志吃满。
遇到问题加QQ23979811 协助处理
Nginx日志切割,按天切割nginx日志
前言
Nginx 的访问日志一直写在一个文件里,越写越大,几百GB都有可能。磁盘满了网站就挂了。本文讲一下怎么用 logrotate 自动按天切割 Nginx 日志。
为什么要切割日志
- 日志太大占磁盘
- 分析大文件慢
- 出问题查日志不方便
方法一:用系统自带的 logrotate
CentOS 自带 logrotate,直接配就行。
第一步:写配置文件
vi /etc/logrotate.d/nginx
内容:
/var/log/nginx/*.log {
daily
missingok
rotate 30
compress
notifempty
create 0644 www www
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
参数说明:
| 参数 | 说明 |
|---|---|
daily |
按天切割 |
rotate 30 |
保留30天的日志 |
compress |
压缩旧日志 |
notifempty |
空文件不切割 |
missingok |
日志文件不存在不报错 |
第二步:测试一下
logrotate -d /etc/logrotate.d/nginx
-d 是调试模式,不会真执行,看一下有没有报错。
第三步:立即执行一次
logrotate -f /etc/logrotate.d/nginx
方法二:自己写脚本
不想用 logrotate,自己写个 shell 脚本:
vi /root/nginx_log.sh
内容:
#!/bin/bash
LOG_PATH=/var/log/nginx
YESTERDAY=$(date -d "yesterday" +%Y%m%d)
cd $LOG_PATH
mv access.log access_$YESTERDAY.log
mv error.log error_$YESTERDAY.log
nginx -s reopen
加执行权限:
chmod +x /root/nginx_log.sh
加到 crontab,每天凌晨执行:
crontab -e
加一行:
0 0 * * * /root/nginx_log.sh
常见坑
坑1:切割后日志不写了
把日志文件改名了,Nginx 还往旧文件写。
原因: Nginx 打开的是文件句柄,改名后它不知道。
解决: 切割后要通知 Nginx 重新打开日志文件:
nginx -s reopen
坑2:旧日志没删,磁盘还是满的
配了切割,但旧日志还留着。
原因: 没配 rotate 参数。
解决: 加上 rotate 30,自动只保留30天。
坑3:压缩太占CPU
所有日志都压缩,CPU 飙高。
解决: 错峰压缩,比如凌晨3点再压缩,或者用 delaycompress 延迟一天再压缩。
坑4:日志权限不对
切割后新日志文件属主不对,Nginx 写不了。
解决: logrotate 配置里加 create 0644 www www。
总结
推荐用 logrotate,系统自带,不用自己维护脚本。
核心配置就这些:
/var/log/nginx/*.log {
daily
rotate 30
compress
postrotate
/bin/kill -USR1 `cat /run/nginx.pid`
endscript
}
记住: 切割完一定要通知 Nginx 重新打开日志文件,不然新日志不写。
遇到问题加QQ23979811 协助处理
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 协助处理
Linux日志过大占用磁盘,logrotate日志切割配置
前言
服务器跑了几个月,突然磁盘满了,一查发现是日志文件占了几十G。Nginx的access.log、MySQL的慢查询日志、系统日志……这些日志文件只会越来越大,不会自己变小。手动删了吧,又怕删出问题;不删吧,磁盘迟早满。Linux 自带了 logrotate 工具,专门用来自动切割和清理日志,配置一次以后就不用管了。本文就详细讲一下怎么用 logrotate 管理日志。
什么是 logrotate
logrotate 是 Linux 系统自带的日志管理工具,可以自动完成:
- 切割日志:把大日志文件按天/按大小切成多个小文件
- 压缩日志:旧的日志自动 gzip 压缩
- 删除日志:保留指定天数后自动删除
- 通知服务:切割完后通知 Nginx/MySQL 等服务重新打开日志文件
系统默认每天运行一次 logrotate,你只需要写好配置文件就行。
logrotate 配置文件结构
全局配置
vi /etc/logrotate.conf
这是全局配置文件,一般不用改。里面定义了默认的行为:
weekly # 默认每周切割一次
rotate 4 # 保留4个日志文件
create # 切割后创建新的空日志文件
dateext # 用日期作为扩展名
include /etc/logrotate.d # 包含这个目录下的所有配置
单个服务的配置
每个服务的日志配置放在 /etc/logrotate.d/ 目录下:
ls /etc/logrotate.d/
比如 nginx、mysql、syslog 都有各自的配置文件。
实战:配置 Nginx 日志切割
我们以 Nginx 为例,写一个完整的 logrotate 配置。
1. 创建配置文件
vi /etc/logrotate.d/nginx
2. 写入配置
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 nginx nginx
postrotate
/usr/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
3. 参数说明
| 参数 | 作用 |
|---|---|
/var/log/nginx/*.log |
要切割的日志文件路径 |
daily |
每天切割一次 |
rotate 30 |
保留30个日志文件 |
compress |
旧日志用gzip压缩 |
delaycompress |
延迟压缩,新切割的当天不压缩 |
missingok |
日志文件不存在不报错 |
notifempty |
空文件不切割 |
create 644 nginx nginx |
创建新文件,权限644,属主nginx |
postrotate...endpostrotate |
切割后执行的命令,通知Nginx重新打开日志文件 |
常用切割策略
按天切割,保留30天
/var/log/nginx/*.log {
daily
rotate 30
compress
missingok
notifempty
create 644 nginx nginx
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
按大小切割,超过100M就切
/var/log/nginx/access.log {
size 100M
rotate 10
compress
missingok
notifempty
create 644 nginx nginx
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
同时按天+按大小
/var/log/nginx/*.log {
daily
size 100M
rotate 30
compress
missingok
notifempty
create 644 nginx nginx
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
endpostrotate
}
意思是每天检查一次,如果日志超过100M就切割。
手动测试 logrotate
配置完之后,可以用 debug 模式测试一下,不会真正执行:
logrotate -d /etc/logrotate.d/nginx
参数说明:
-d:debug模式,只显示会做什么,不真正执行
如果没问题,手动执行一次:
logrotate -f /etc/logrotate.d/nginx
-f:强制切割,不管到没到时间
常见坑
坑1:切割了但服务还在写旧文件
很多人配置完 logrotate,发现日志切完了,但磁盘空间没释放。这是因为 Nginx 还在往旧的日志文件里写(虽然名字改了,但文件句柄还在)。
解决: 一定要配置 postrotate 脚本,通知服务重新打开日志文件。对于 Nginx,就是发送 USR1 信号:
postrotate
/bin/kill -USR1 `cat /run/nginx.pid`
endpostrotate
坑2:压缩延迟没开,旧日志还占着空间
如果不加 delaycompress,切割完立刻就压缩,但服务可能还在写旧文件,导致压缩失败或者压缩不完整。
解决: 加上 delaycompress,让新切割的日志第二天再压缩。
坑3:日志文件权限不对
切割完创建的新日志文件,如果属主不对,Nginx 就写不进去。
解决: 用 create 644 nginx nginx 指定新文件的属主和权限。
坑4:logrotate 不执行
配置写完了,但日志从来没切割过。检查一下:
# 看logrotate的cron任务有没有
cat /etc/cron.daily/logrotate
# 手动执行一次看有没有报错
logrotate -d /etc/logrotate.d/nginx
总结
logrotate 配置的核心步骤:
- 在
/etc/logrotate.d/下创建配置文件 - 指定日志路径、切割频率、保留数量
- 加上
postrotate通知服务重新打开日志 - 用
logrotate -d测试配置 - 系统每天自动执行,不用管了
日志切割是服务器运维的基本功,配好了以后磁盘永远不会被日志撑满。
遇到问题加QQ23979811 协助处理