日志自动清理定时脚本避免磁盘爆满服务器宕机
日志自动清理定时脚本,是服务器运维中防止磁盘爆满、避免服务宕机的重要手段。
通过编写 Shell 脚本定期清理 /var/log 及业务日志目录,再配合 crontab 定时执行,可以在日志量失控前自动释放磁盘空间。
本文面向零基础用户,讲清楚从检查磁盘、写脚本到验证结果的全过程,并列出新手最容易踩的坑。
先看清磁盘是否被日志占满
在动手写脚本之前,先确认磁盘使用情况和日志文件大小,避免盲目清理。
登录服务器后执行:
df -h
查看各分区使用率,重点看挂载点为 / 的一行。
如果使用率超过 80%,就需要进一步定位大日志文件:
sudo du -sh /var/log/* 2>/dev/null | sort -rh | head -20
同时也要检查业务日志目录,比如常见的 /data/logs、/www/wwwlogs 等。
定位之后,再决定清理哪些路径和保留多长时间。
按需求编写日志清理脚本
清理日志不能直接删除目录,更不要用 rm -rf 删正在写入的文件。
推荐的做法是保留最近 N 天的文件,并清空当前正在被进程占用的日志。
下面是一个通用脚本示例:
#!/bin/bash
# 日志自动清理脚本 - 保留最近 7 天
LOG_DIRS=("/var/log" "/data/logs") # 按实际路径修改
RETENTION_DAYS=7
for dir in "${LOG_DIRS[@]}"; do
if [ -d "$dir" ]; then
# 删除超过保留天数的 .log 和 .log.* 文件
find "$dir" -type f \( -name "*.log" -o -name "*.log.*" \) -mtime +$RETENTION_DAYS -exec rm -f {} \;
# 清空当前正在写入的 .log 文件,不删除文件本身
find "$dir" -type f -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null
fi
done
echo "$(date '+%Y-%m-%d %H:%M:%S') 日志清理完成" >> /var/log/log-clean.log
把脚本保存为 /usr/local/bin/clean_logs.sh,然后赋予执行权限:
sudo chmod +x /usr/local/bin/clean_logs.sh
脚本里的 LOG_DIRS 数组需要改成你服务器上实际的日志目录,RETENTION_DAYS 可按磁盘剩余空间调整。
注意,truncate -s 0 用于清空当前文件内容,这样即使程序仍在写入日志,也不会因为文件被删除而出问题。
配置 crontab 实现每天自动执行
手动执行脚本只能解决一次问题,真正避免磁盘爆满还需要定时触发。
编辑当前用户的 crontab:
crontab -e
如果是第一次编辑,需要选择编辑器,一般选 nano 或 vim。
加入这一行,表示每天凌晨 2 点执行清理:
0 2 * * * /usr/local/bin/clean_logs.sh
保存并退出。
查看定时任务是否生效:
crontab -l
如果希望脚本日志能帮助排查问题,可以把脚本输出追加到固定文件,上面的脚本已经写入了 /var/log/log-clean.log。
建议不要把输出直接发到邮箱,免得日志量大时刷爆邮箱。
新手最容易踩的坑
第一,不要用 rm 直接删正在被进程占用的日志文件。 删除后进程仍然持有旧文件的 inode,磁盘空间不会真正释放,还会出现文件句柄泄漏。
正确做法是用 truncate 清空文件内容。
第二,find 的 -mtime +N 含义是“超过 N 天”,N 要按实际保留需求设置。 如果写成 -mtime -7,意思会变成“7 天以内”,正好搞反。
第三,不要把所有日志目录都纳入清理范围。 有些程序有特殊权限或正在输出重要审计日志,建议先观察几天,确认没有影响再纳入脚本。
第四,清理脚本本身也要监控。 可以顺手用 du -sh /var/log 比较清理前后大小,或者在脚本里加一个磁盘使用率阈值判断,超过 90% 时额外执行一次深度清理。
如果你用的是云服务器,比如泽御云这类持证服务商提供的云主机,也可以直接在控制台查看磁盘监控图表,结合脚本清理,双保险更有底。
验证清理效果是否正常
配置完成后,不要干等第二天。
先手动执行一次脚本,确认输出和磁盘变化:
sudo bash /usr/local/bin/clean_logs.sh
然后查看磁盘使用率:
df -h / | tail -1
如果清理前后使用率有明显下降,说明脚本有效。
接着检查日志清理记录:
cat /var/log/log-clean.log
最后确认 crontab 任务确实在跑,可以把执行时间临时改成下一分钟测试,比如 * * * * *,看到结果后再改回凌晨 2 点。
注意测试期间的输出会多一条,别影响正式任务。
常见问题解答
问:日志文件特别大,但 find 删除后磁盘空间没释放?
答:很可能是文件正被进程占用。
不要用 rm,改用 truncate -s 0 文件路径 清空内容,空间会立即释放。
问:crontab 生效了吗?
怎么确认?
答:用 crontab -l 查看已添加任务,grep CRON /var/log/syslog(或 /var/log/cron)可以看执行记录。
也可以故意在脚本里写错路径,观察报错日志。
问:业务日志不能随便删,怎么保留更久?
答:先做日志轮转(logrotate),把日志按天或按大小切割成历史文件,再对历史文件执行 -mtime +30 清理,业务日志本身不动。
问:清理脚本可以处理多个目录吗?
答:可以。
在 LOG_DIRS 数组里加多个路径即可,但要注意每个目录的保留天数可能不同,更精细的场景建议拆成多个 find 语句分别设置。
按照上面的步骤配置好日志自动清理定时脚本,你就不必每天手动盯磁盘。
唯一要记住的是:清理策略要保守,保留时间宁可长一点,也不要误删有用日志。
如果后续日志量继续增大,再结合 logrotate 和监控告警做体系化优化。