日志自动清理脚本防止磁盘占满宕机
日志文件是服务器记录运行状态的必要产物,但如果不加控制,它们会悄然吞噬磁盘空间,最终导致服务崩溃甚至 SSH 无法登录。
本文提供两套方案:一是系统自带的 logrotate 工具,二是自定义 find + crontab 脚本。
无论你用哪种面板,底层原理通用,零基础也能一步步实现日志自动清理。
第一步:确认哪些日志在吃磁盘
登录服务器,执行以下命令查看各日志目录占用:
df -h
# 查看各分区使用率,重点关注 /var 分区
du -sh /var/log/*
# 列出 /var/log 下每个文件或文件夹的大小
重点关注 messages、syslog、secure、nginx 和 mysql 的日志。
如果某个文件超过几百 MB,就需要纳入清理计划。
Nginx 和 MySQL 日志通常也在 /var/log/nginx/ 和 /var/log/mysql/ 下。
第二步:使用 logrotate 实现自动轮转(推荐)
logrotate 是 Linux 自带的日志管理工具,支持按大小、日期自动切割、压缩和删除旧日志。
2.1 编写一个自定义配置
例如处理 Nginx 日志(假设 Nginx 日志在 /var/log/nginx/),新建文件 /etc/logrotate.d/nginx:
/var/log/nginx/*.log {
daily # 每天轮转一次
rotate 7 # 保留最近 7 份
compress # 轮转后的日志压缩
delaycompress # 留一份未压缩的以便查看
missingok # 日志不存在时不报错
notifempty # 空日志不轮转
create 0640 nginx adm
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
关键参数说明:rotate 7 只保留 7 个历史文件,超出的自动删除;compress 用 gzip 压缩。
替换成你的实际路径(如 /var/log/httpd/*.log)即可。
2.2 测试配置是否正确
sudo logrotate -d /etc/logrotate.d/nginx
# -d 为调试模式,仅模拟,不会实际执行
如果输出没有报错,再手动强制执行一次验证:
sudo logrotate -f /etc/logrotate.d/nginx
ls -lh /var/log/nginx/
你应该能看到 access.log.1.gz 之类的文件,说明轮转成功。
第二步(备选):自定义 find+rm 清理脚本
如果系统没有 logrotate 或者你想更灵活地控制(例如只保留最近 3 天的日志),可以写一个简单的清理脚本:
#!/bin/bash
# 清理超过 7 天的 .log 文件
LOG_DIR="/var/log/nginx"
find "$LOG_DIR" -name "*.log" -type f -mtime +7 -exec rm -f {} \;
保存为 /usr/local/bin/clean_old_logs.sh,并赋予执行权限:
chmod +x /usr/local/bin/clean_old_logs.sh
然后通过 crontab 定时执行:
crontab -e
# 添加一行,每天凌晨 3 点执行
0 3 * * * /usr/local/bin/clean_old_logs.sh
注意:find 命令默认只处理普通文件,如果日志被压缩成 .gz,需要再加上 -name "*.gz"。
也可以一步全清:find "$LOG_DIR" -type f \( -name "*.log" -o -name "*.gz" \) -mtime +7 -delete(-delete 是 find 内置删除,安全但谨慎)。
避坑指南
- 权限问题:清理脚本必须以 root 或日志所属用户执行,否则无法删除。crontab 建议用 root 账户配置。
- 日志还在写入:直接用
rm -f赶跑日志文件后,如果对应进程还持有文件描述符,磁盘空间不会立即释放。推荐先truncate -s 0清空文件内容,或使用 logrotate 配合postrotate重启/重载服务。 - 时间单位:
-mtime +7表示修改时间超过 7 天(不含当天),测试时建议先用-mmin +60这样的小单位验证。 - 不要删除正在用的日志:如果脚本不慎删除了当前正在写入的访问日志,可能会造成 Nginx 写出错。logrotate 的
copytruncate模式可以避免此问题。
效果验证
执行清理后(或等待下一次定时任务),通过以下方式确认:
- 检查磁盘使用率:
df -h,看/var分区是否下降。 - 查看日志目录:
ls -lh /var/log/nginx/,确认旧文件已删除或轮转。 - 查看 crontab 执行记录:
grep clean_old_logs /var/log/cron(如果系统开启了 cron 日志)。 - 对于 logrotate,查看状态文件
cat /var/lib/logrotate/status确认最后执行时间。
高频问题解答
- 问:我的日志在
/data/logs而非/var/log,能通用吗?
答:完全可以。
logrotate 配置或 find 脚本里把路径改成你的实际目录即可。
- 问:日志自动清理脚本跑完后,磁盘空间没变?
答:可能因为日志进程仍在写那个文件。
执行 lsof | grep deleted 看是否有已删但仍被占用的文件,然后重启该服务或执行 kill -USR1 进程PID。
- 问:我不懂 Linux 命令,有没有面板方案?
答:宝塔面板内置日志清理功能,在“计划任务”中添加“释放内存”或“切割日志”任务;
1Panel 也可在计划任务中选择“日志清理”。
但原理与本文命令一致。
如果你正在处理日志自动清理脚本防止磁盘占满宕机的问题,建议先按本文步骤完整执行,再根据自己的环境做微调;
遇到异常时优先回看避坑和高频问题部分。
定时清理一旦跑顺,基本可以安心很久。