日志自动清理定时脚本避免磁盘爆满宕机
很多刚接触服务器的朋友遇到过这样的情况:网站忽然打不开,SSH连不上,最后发现是磁盘写满了,90%的罪魁祸首是不断膨胀的日志文件。
本文教你用一条简单的定时脚本,自动清理过期日志,从根源避免磁盘爆满宕机。
一、先确认哪些日志在吃你的磁盘
在写脚本之前,先登录服务器,用 du 命令看看日志目录有多大。
绝大多数 Linux 发行版的系统日志在 /var/log/ 下,Nginx、Apache、MySQL 等应用日志也常落在这个目录或独立路径。
# 查看 /var/log 目录总大小
du -sh /var/log
# 列出目录下最大的5个文件或子目录
du -sh /var/log/* | sort -rh | head -5
如果发现某个日志文件(比如 syslog、messages 或 access.log)已经几百 MB 甚至 GB 级,就可以把它加入清理名单。
同时也要确认应用日志的路径,例如:
- Nginx 日志:通常位于
/var/log/nginx/ - Apache 日志:通常位于
/var/log/httpd/或/var/log/apache2/ - MySQL 慢查询日志:通常位于
/var/log/mysql/或自定义路径
二、编写一个通用的日志清理脚本
清理日志的核心思路是:保留最近 N 天的文件,删除更早的。
Linux 自带的 find 命令就能轻松做到。
创建一个脚本文件:
sudo touch /usr/local/bin/clean_logs.sh
sudo chmod +x /usr/local/bin/clean_logs.sh
然后用任意编辑器写入以下内容:
#!/bin/bash
# 日志自动清理脚本 - 保留7天,删除7天前的日志
# 可根据需要修改 DAYS 和 LOG_DIRS 数组
DAYS=7
LOG_DIRS=(
"/var/log"
"/var/log/nginx"
"/var/log/httpd"
"/var/log/mysql"
)
for dir in "${LOG_DIRS[@]}"; do
if [ -d "$dir" ]; then
find "$dir" -type f -name "*.log" -mtime +$DAYS -exec rm -f {} \;
echo "$(date): 已清理 $dir 中 $DAYS 天前的日志文件"
fi
done
注意:这里只删了扩展名为.log的文件。如果你的日志没有.log后缀(比如messages、syslog),需要自行调整-name参数,或者直接用-name "*"配合-type f。但建议只删除明确知道是日志的文件,避免误删系统配置。
三、用 crontab 定时执行脚本
编写完脚本后,设置定时任务,让它在每天凌晨执行一次(此时系统负载低,且能清掉前一天的全部日志)。
# 打开当前用户的 crontab 编辑器
crontab -e
在最后添加一行:
0 3 * * * /usr/local/bin/clean_logs.sh >> /var/log/clean_logs.log 2>&1
解释一下:
0 3 * * *表示每天凌晨 3:00 执行/usr/local/bin/clean_logs.sh是脚本的绝对路径>> /var/log/clean_logs.log 2>&1把执行日志(包括错误)追加到另一个文件,方便日后排错
如果用的是宝塔面板,可以在“计划任务”里添加:任务类型选择 shell,执行周期选每天 3:00,脚本内容粘贴上面的 clean_logs.sh 内容(不含 #!
/bin/bash 前面的部分),无需再手动写 crontab。
四、常见问题与避坑清单
1. 脚本执行了但文件没删?
- 检查脚本权限是否可执行(
ls -l /usr/local/bin/clean_logs.sh),如果缺少x权限,运行chmod +x。 - 检查日志文件的修改时间:
mtime以最后一次修改时间为准,如果日志一直在滚动写入,-mtime +7可能只删掉完全没变动的旧文件。对于按日期滚动的日志(如access.log-20250401),可以直接用-mtime,但对于同一个文件(如access.log不滚动),find不会删除正在写入的文件。更稳妥的做法是配置日志轮转(logrotate),而不是直接删除。 - 如果某目录路径不存在,脚本会静默跳过,建议先手动
ls确认路径。
2. 误删了需要的文件?
- 建议先在
find命令里加上-exec ls -l {} \;测试确认要删哪些文件,确认无误再换成-exec rm -f。也可以在正式执行前先跑一次find ... -exec echo {} \;看看列表。
3. crontab 不执行?
- 检查 crontab 是否保存成功:
crontab -l。 - 手动执行脚本看报错:
bash /usr/local/bin/clean_logs.sh。 - 查看系统邮件(如果没重定向输出):
tail -20 /var/spool/mail/用户名。 - 确保脚本中使用了绝对路径,crontab 的环境变量有限。
五、验证清理效果
设置好定时任务后,可以先手动跑一次脚本,然后马上查看磁盘空间变化:
# 手动执行
sudo bash /usr/local/bin/clean_logs.sh
# 查看日志目录大小
du -sh /var/log
# 查看根分区磁盘使用率
df -h /
如果脚本输出正常并且磁盘使用率下降,说明定时任务生效。
第二天再登录检查 df -h 和 /var/log/clean_logs.log 中是否有执行记录。
另外,建议同时检查一下是否存在不按 .log 后缀命名的日志文件(如 cron, maillog),如果有需要,单独在脚本里加一条 find /var/log -type f -name "cron" -mtime +7 -delete。
给脚本增加排除项也能提高安全性。
如果你用的是 Nginx、Apache 或 MySQL,还有一个更优雅的办法——配置 logrotate,不过那需要修改配置文件。
本文的 find+rm 方案胜在简单直接,适合快速上手避免磁盘爆满宕机。
当服务器上已经出现磁盘告警时,优先用这个方案紧急释放空间。