日志自动清理定时脚本避免磁盘爆满服务器宕机部署
服务器日志自动清理定时脚本部署指南,避免磁盘爆满导致宕机
日志文件是排查问题的好帮手,但它们不会自己消失。
几个月不清理,/var/log 目录可能膨胀到几十GB,最终把磁盘塞满,导致服务异常甚至服务器宕机。
本文专门解决这个问题:写一个自动清理脚本,再用系统定时任务(crontab)让它每天执行一次,全程零基础可跟做。
动手之前先检查这些
在写脚本之前,先确认三件事:
- Linux 系统:本文基于 CentOS 7/8、Ubuntu 20.04+,其他发行版命令相同。
- 你有 root 权限:脚本涉及删除文件,需要用 root 或 sudo 执行。
- 了解日志位置:常见目录是
/var/log,你的应用日志可能在/app/logs或/home/project/logs,先确认好。
如果还不清楚日志路径,用 df -h 查看磁盘使用率,再用 du -sh /var/log 看日志占了多少空间。
一步步写出自动清理脚本
我们要的脚本很简单:删除指定目录下超过 N 天的日志文件,保留近期的。
在你喜欢的位置创建一个脚本文件,比如 /usr/local/bin/clean_logs.sh:
sudo nano /usr/local/bin/clean_logs.sh
粘贴以下内容:
#!/bin/bash
# 自动清理过期日志脚本
# 用法:修改 LOG_DIR 和 DAYS 变量即可
# 要清理的日志目录,多个用空格隔开
LOG_DIRS=("/var/log" "/app/logs")
# 保留最近多少天的日志
DAYS=7
# 日志文件后缀(通常 .log .out .txt .gz 等)
EXTENSIONS=("*.log" "*.gz" "*.out" "*.txt")
for dir in "${LOG_DIRS[@]}"; do
if [ -d "$dir" ]; then
for ext in "${EXTENSIONS[@]}"; do
find "$dir" -type f -name "$ext" -mtime +$DAYS -exec rm -f {} \;
done
echo "已清理 $dir 中超过 $DAYS 天的日志"
else
echo "警告:目录 $dir 不存在,跳过"
fi
done
保存退出后,给脚本执行权限:
sudo chmod +x /usr/local/bin/clean_logs.sh
关键解释:
-mtime +$DAYS表示文件修改时间超过 N 天。rm -f强制删除,不询问。- 日志目录和保留天数可按实际修改。
如果你需要保留某些关键日志(比如 access.log),可以单独加排除规则,后续避坑部分会讲。
用crontab让脚本定时跑起来
脚本写好了,手动运行没问题后,就交给 crontab。
执行 sudo crontab -e(用 root 身份编辑)或直接普通用户加 sudo:
sudo crontab -e
如果第一次使用,会提示选择编辑器,选 nano 或 vim 都可以。
在文件末尾添加一行:
0 3 * * * /usr/local/bin/clean_logs.sh >/dev/null 2>&1
这行表示每天凌晨 3:00 执行脚本,并将输出丢入黑洞(不产生垃圾邮件)。
保存退出即可。
cron 字段说明:
- 第1个
0:分钟(0) - 第2个
3:小时(3点) - 第3个
*:日(每天) - 第4个
*:月(每月) - 第5个
*:星期(每天)
你也可以改成 0 2 * * 0 每周日凌晨2点运行,看自己需求。
这些坑一定要提前避开
脚本权限不正确
脚本必须有执行权限(chmod +x),并且由 root 运行才能删除所有日志。
如果普通用户运行,可能会因权限不足报错。
日志文件正在被写入时删除
delete 操作本身不会导致程序崩溃(Linux 文件句柄机制),但删除后原文件消失,程序会新建一个空文件。
如果程序写日志时不自动创建新文件,可能导致日志丢失。
保险做法:先重启应用,或使用 logrotate 更优雅。
但对于纯文本日志,直接删没问题。
误删关键日志
如果你的日志目录包含其他重要文件(比如数据库备份),可以用排除参数。
例如只删除 .log 和 .gz,并在脚本中加上排除:
find "$dir" -type f \( -name "*.log" -o -name "*.gz" \) -mtime +$DAYS ! -name "important.log" -exec rm -f {} \;
如何验证脚本生效了
1. 手动运行一次
sudo /usr/local/bin/clean_logs.sh
查看终端打印的信息,确认是否存在目录不存在等提示。
2. 对比磁盘使用
运行前和后分别执行:
df -h /var/log
du -sh /var/log
如果清理成功,占用空间应减少。
3. 检查 crontab 是否加载
sudo crontab -l
确认有刚添加的那一行。
4. 查看 cron 执行日志
不同系统路径不同:
- CentOS/RHEL 7+:
/var/log/cron - Ubuntu:
systemctl status cron或grep clean_logs /var/log/syslog
如果有 CMD 字样表示已执行,查看返回状态。
常见问题与解决方法
Q:脚本运行了但日志没删?
A:检查 DAYS 是否写得太小(比如0),或者 find 命令没有匹配到文件。手动执行 find /var/log -type f -name "*.log" -mtime +7 看是否有输出。
Q:如何调整保留天数?
A:修改脚本中的 DAYS=7 为其他数字,比如 30 天。然后重新执行一次脚本(或等下次定时触发)。
Q:可以同时清理多个目录?
A:在 LOG_DIRS 数组中用空格添加更多路径即可,比如 ("/var/log" "/app/logs" "/home/www/logs")。
Q:定时任务没启动?
A:先确认 cron 服务是否运行:systemctl status crond(CentOS)或 systemctl status cron(Ubuntu)。如果没运行,执行 systemctl start crond。
总结
通过一个简单的 Shell 脚本加一行 crontab 配置,就能彻底解决日志文件撑爆磁盘的老大难问题。
本文的脚本已经经过实战检验,你只需根据自己环境微调目录和保留天数。
如果遇到权限、路径、cron 不生效等问题,回看“避坑”和“常见问题”部分就能解决。
建议部署后连续观察两三天,确认清理日志正常运行后就可以安心了。
如果你还想了解更专业的日志轮转工具(logrotate),可以参考本站的另一篇文章:《logrotate配置详解,优雅管理服务器日志》——无需自己写脚本,也能自动压缩、删除旧日志。