这个脚本解决什么问题?
服务器跑久了,/var/log 下的日志会无限增长。今天几个 MB,下个月几个 GB,不知不觉就把磁盘写满。磁盘满了的后果很严重:系统变慢、服务崩溃、数据写不进去,甚至整个机器卡死。
运维每天手动删日志既不现实也不安全(容易误删),所以最合理的做法是写一个脚本,让它自己判断什么该删、什么该留、怎么删才不伤服务,然后用定时任务每天自动跑。
脚本全文
用途: 自动删除超过保留天数的滚动日志,并清空过大的当前日志(保留文件句柄、无需重启服务),防止磁盘被日志堆满。
#!/bin/bash
LOG_DIR="/var/log"
KEEP_DAY=7 # 保留天数:7 天前的旧日志就清掉
# 第一步:删除 7 天前的滚动日志
# 滚动日志形如 x.log.1、x.log.2.gz,是历史旧文件,可以放心删
find "$LOG_DIR" -name "*.log.*" -type f -mtime +"$KEEP_DAY" -exec rm -f {} \;
# 第二步:清空超大但还在用的当前日志
# 用 truncate 而不是 rm:保留文件本身,释放空间又不断服务写句柄
find "$LOG_DIR" -name "*.log" -type f -mtime +"$KEEP_DAY" -size +50M -exec truncate -s 0 {} \;
echo "[$(date '+%F %T')] 日志清理完成"
一行行看懂它
find "$LOG_DIR" -name "*.log.*" -type f:在日志目录里找”文件名带两个点”的这种滚动日志(xxx.log.1这种历史文件)。-mtime +7:只处理修改时间在 7 天以前的文件。-exec rm -f {} \;:对每个匹配到的文件执行删除。- 第二步里的
truncate -s 0:把文件内容清空但保留文件本身。这是关键细节——如果直接rm正在被服务写的日志,文件句柄还占着,磁盘空间不会真正释放;truncate既释放了空间,又让服务能继续写,还不用重启。
怎么用
vim clean_log.sh # 把上面脚本贴进去保存
chmod +x clean_log.sh # 加执行权限
./clean_log.sh # 手动跑一次看效果
crontab -e # 再配定时,每天凌晨 2 点自动跑
# 加入这一行:
0 2 * * * /root/scripts/clean_log.sh
常见坑
| 现象 | 原因 | 解决 |
|---|---|---|
Permission denied | 没加执行权限 | chmod +x clean_log.sh |
| 提示找不到文件 | 路径用了相对路径 | 脚本里路径写绝对,例如 /var/log |
| 日志没被删 | 时间条件不对 | 先 find /var/log -name "*.log.*" 看文件时间,再调 KEEP_DAY |
小结
清理日志的核心不是”删文件”,而是“只删该删的、删的时候不伤服务”。find 负责精准挑选,-mtime 负责控制时间,truncate 负责安全释放。这一个脚本,配合 crontab,就能让你再也不用担心”磁盘半夜满了”。