定时清理磁盘日志防止站点磁盘爆满
为什么你的站点磁盘总在悄悄被撑爆
很多新手站长接到磁盘告警时,第一反应是检查网站文件,却发现 /var/log 目录下躺着几十个 G 的日志文件。
Nginx、MySQL、PHP-FPM 每天都在吐日志,如果不加控制,几个月就能把一块 40G 的硬盘填满。
一旦磁盘写满,数据库会直接挂掉,网站返回 500 错误,甚至连 SSH 都登不进去。
本文要解决的就是这个最隐蔽又最要命的磁盘杀手。
准备:先确认你的日志有多大
在动手清理之前,先登录服务器执行一条命令看看哪些日志最吃空间:
df -h # 查看整体磁盘使用率
du -sh /var/log/* | sort -rh | head -10 # 找 /var/log 下最大的10个文件或目录
如果你用的是宝塔面板,可以直接在“文件”里查看 /www/wwwlogs 目录,Nginx 的 access.log 经常单文件就超过 5G。
另外别忘了 MySQL 慢查询日志和 PHP 错误日志,它们也容易堆积。
操作:用 logrotate 自动切割并压缩日志
大多数 Linux 发行版自带了 logrotate,但配置默认只对系统日志有效。
我们要给它加一条针对 Web 日志的规则。
第一步:创建自定义配置文件
sudo nano /etc/logrotate.d/nginx-custom
填入以下内容(根据你的日志路径调整):
/var/log/nginx/*.log {
daily # 每天轮转一次
rotate 7 # 保留最近7个归档
compress # 压缩旧日志为 .gz
delaycompress # 压缩延迟一次,保证正在写入的日志不会立即压缩
missingok # 日志文件不存在不报错
notifempty # 日志为空不轮转
create 0640 nginx adm # 新建日志文件的权限和用户组
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
这段配置的含义:每天轮转一次,只保留一周的日志,旧日志自动压缩成 .gz,轮转后向 Nginx 发送信号重新打开日志文件。
第二步:测试配置是否生效
sudo logrotate -d /etc/logrotate.d/nginx-custom
-d 是调试模式,只会模拟执行,不会真的删除。
看输出有没有语法错误或者路径错误。
如果没有问题,再手动强制执行一次:
sudo logrotate -f /etc/logrotate.d/nginx-custom
执行后去 /var/log/nginx 目录下看看,应该已经有 .gz 压缩包了。
第三步(可选):如果服务器没有 logrotate 怎么整
极个别精简系统可能没装 logrotate,可以用 crontab + 脚本替代。
比如每周日凌晨压缩并清理 7 天前的日志:
0 4 * * 0 find /var/log/nginx -name "*.log" -mtime +7 -exec gzip {} \; && find /var/log/nginx -name "*.gz" -mtime +30 -delete
这条 crontab 会把 7 天前的日志压缩,30 天前的压缩包删除。
不过还是建议优先安装 logrotate,功能更完善。
避坑:这 3 个细节不注意等于白忙
🚫 别直接 rm 删除正在运行的日志
很多新手直接用 rm -rf /var/log/nginx/access.log,然后发现磁盘空间没释放。
因为文件句柄还被 Nginx 持有,删除文件只是断开了文件名,实际空间要等重启或 kill -USR1 才会释放。
一定要用 logrotate 的 postrotate 做 reopen。
🚫 日志权限别改错
如果新建的日志文件权限不对,Nginx 写日志会报 403。
配置 create 0640 nginx adm 时,确保 nginx 用户和 adm 组真实存在。
🚫 监控别忘了 MySQL
很多人只清理 Web 日志,MySQL 的 slow_query_log 和 general_log 同样能吃满磁盘。
如果你的数据库日志在 /var/lib/mysql 里,建议单独写一个 logrotate 配置:
/var/lib/mysql/*.log {
daily
rotate 3
compress
missingok
notifempty
create 0640 mysql mysql
postrotate
mysqladmin flush-logs
endscript
}
execute mysqladmin flush-logs 前要确保 MySQL 密码已配置好无需交互。
验证:怎么确认磁盘不会再突然爆满
查看 logrotate 执行记录
logrotate 的执行记录通常在 /var/log/logrotate/logrotate.log 或 syslog 里,搜一下:
grep logrotate /var/log/syslog | tail -5
能看到每次轮转的时间和处理的文件。
监控磁盘剩余空间
写一个简单的 crontab 每天把磁盘使用率发到邮箱或告警群:
0 8 * * * df -h | mail -s "磁盘使用报告" your@email.com
或者用宝塔面板的“监控报警”直接配置磁盘占用超 80% 发消息。
高频率问题解答
Q: 日志太多,设置 daily 轮转还是不够怎么办?
A: 改 size 100M 代替 daily,按大小轮转,日志超过 100MB 就切一次。
Q: 宝塔面板怎么设置定时清理?
A:
宝塔后台“计划任务”里选“脚本”,
填入 logrotate 命令,
比如 logrotate -f /etc/logrotate.d/nginx-custom,
每天凌晨执行一次。
Q: delete 旧压缩包时会不会误删?
A: 只要文件名有 .gz 并且用 -mtime +30 限制天数,不会误删其他文件。
建议先 find 不带 -delete 预览一下。
以上就是一套从零开始让服务器日志自动滚动的完整方案,按照步骤配置完成后,磁盘爆满的问题基本就不会再出现了。
如果遇到其它日志路径,比如 PHP 的 error_log,用同样的方法添加一条配置即可。
记住一条原则:只要日志有规律地自动清理,站点就安全一大半。