磁盘空间爆满自动清理无用日志定时任务脚本
服务器磁盘空间爆满时,最常见的元凶就是不断增长的日志文件。
解决思路是用一个 shell 脚本配合 crontab 定时任务,自动删除或压缩指定时间之前的日志,从而持续释放磁盘空间。
本文会从排查磁盘占用开始,逐步写出清理脚本、配置定时任务,并给出常见报错和验证方法,零基础用户也能直接照做。
先确认磁盘到底被什么占满
在写脚本之前,先登录服务器执行下面两条命令,确认磁盘使用率和占用最大的目录:
df -h
du -sh /var/log/* | sort -rh | head -20
df -h 能看到各分区已用空间和剩余空间,du 则列出 /var/log 下每个日志文件或目录的大小,按从大到小排序。
如果发现某个日志文件已经好几个 GB,那它就是清理的重点对象。
如果根分区 / 使用率达到 90% 以上,
建议先手动清出一点空间,
比如用 journalctl --vacuum-size=200M 清理 systemd 日志,
再继续配置自动任务。
编写日志清理脚本
这里以一个通用脚本为例:删除指定目录下超过 7 天的 .log 文件和 .gz 压缩日志,同时保留最近 7 天的日志供排查问题。
先创建脚本文件:
vi /usr/local/bin/clean_logs.sh
粘贴以下内容:
#!/bin/bash
# 自动清理无用日志脚本
LOG_DIRS="/var/log /home/project/logs"
KEEP_DAYS=7
for dir in $LOG_DIRS; do
if [ -d "$dir" ]; then
find "$dir" -type f \( -name "*.log" -o -name "*.gz" \) -mtime +$KEEP_DAYS -delete
echo "$(date '+%Y-%m-%d %H:%M:%S') 已清理 $dir 中超过 ${KEEP_DAYS} 天的日志" >> /var/log/clean_logs.log
fi
done
保存后给脚本添加执行权限:
chmod +x /usr/local/bin/clean_logs.sh
脚本逻辑说明:
LOG_DIRS:要清理的目录列表,根据你的实际情况修改。KEEP_DAYS=7:只删除修改时间超过 7 天的文件。find ... -delete:直接删除匹配的文件。- 每次执行会写一条清理记录到
/var/log/clean_logs.log,方便回溯。
配置 crontab 定时任务
使用 crontab 让脚本每天凌晨自动执行一次。
运行:
crontab -e
如果你是第一次编辑,系统会让你选择编辑器,选 nano 或 vim 都可以。
在文件末尾添加一行:
0 2 * * * /usr/local/bin/clean_logs.sh >/dev/null 2>&1
这行配置的意思是:每天凌晨 2 点执行一次清理脚本,并把标准输出和错误输出都丢弃,避免产生新的垃圾文件。
保存退出后,crontab 会自动加载新任务。
查看定时任务是否已生效:
crontab -l
应该能看到刚才添加的那行配置。
避坑指南:这些情况别乱清
不要直接清空正在被进程写入的日志文件。
像 Nginx、Tomcat 这类服务,如果直接用 echo > access.log 清空内容,可能会因为文件句柄未释放导致磁盘空间仍然不释放。
正确做法是先 rm 删除文件,再重启服务或使用 logrotate 让程序重新创建文件。
数据库日志不要用普通脚本删。
MySQL、PostgreSQL 的 binlog 和 WAL 日志有专门的管理方式,手动删会导致主从同步异常。
这类日志请使用数据库自带命令清理,比如 MySQL 的 PURGE BINARY LOGS。
-mtime +7 与 -mmin 不要混淆。mtime 是按天计算,mmin 是按分钟计算。
测试时建议先用 find /var/log -name "*.log" -mtime +7 -print 查看匹配的文件列表,确认无误后再加 -delete。
验证清理效果
配置完先手动执行一次脚本,确认没有报错:
/usr/local/bin/clean_logs.sh
再查看磁盘空间是否下降:
df -h
同时检查脚本自己的日志:
cat /var/log/clean_logs.log
如果想确认定时任务真的在跑,可以等第二天再看日志文件是否有新记录。
部分系统用 cron 服务需要手动启动,执行 systemctl status crond 检查状态,如果没有启动就运行 systemctl start crond。
常见问题解答
Q:脚本执行了但磁盘空间没变化?
可能是日志文件正在被进程占用,删除后空间不释放。用 lsof | grep deleted 查找已删除但仍被占用的文件,然后重启对应服务。
Q:不想删除日志,只想压缩可以吗?
可以。把脚本里的 -delete 换成 -exec gzip {} \;,这样超过 7 天的日志会被压缩成 .gz,而不是直接删除。
Q:如何让日志保留 30 天而不是 7 天?
修改脚本里的 KEEP_DAYS=30,再重新执行脚本即可,crontab 配置不用改。
Q:crontab 没有执行是什么原因?
先确认 crond 服务是否运行,再看脚本是否有执行权限,最后检查脚本里的目录路径是否存在。也可以在 crontab 中临时去掉 >/dev/null 2>&1,让错误输出到邮件或文件里排查。