用 Shell 脚本给日志做轮转与告警:从磁盘告急到自动清理
【摘要】 日志写满磁盘是常见故障:本文用 Shell 实现按天轮转、按大小兜底、14 天保留清理和 80% 磁盘阈值告警,并给出定时任务与上线验证清单。
日志最常见的死法不是写错,而是写太多。服务跑着跑着磁盘满了,进程先写不进日志,随后写不进数据,最后连登录排障都受影响。本文给出一套可直接落地的 Shell 做法:按天轮转、按大小兜底、保留期清理、磁盘阈值告警,四件事分开做,互不耦合。
先定规则,再写脚本
轮转前先回答四个问题:日志在哪、按什么切、留多久、满了怎么办。建议:应用日志统一放在 /var/log/app/,文件名带日期;每天 0 点切一次,单个文件超过 100MB 也切;压缩后保留 14 天;磁盘使用率超过 80% 发告警,超过 90% 先删最旧的压缩包再告警。规则写进脚本注释里,后面的人不用猜。
轮转脚本示例
#!/bin/bash
set -euo pipefail
LOG_DIR=/var/log/app
KEEP_DAYS=14
cd "$LOG_DIR"
for f in *.log; do
[ -e "$f" ] || continue
mv "$f" "$f.$(date +%F)"
done
find "$LOG_DIR" -type f -name '*.log.*' -mtime +$KEEP_DAYS -delete
gzip -f "$LOG_DIR"/*.log.$(date +%F) 2>/dev/null || true
注意三点:第一,mv 再让应用重新打开文件句柄,必要时发信号重载;第二,删除前先按修改时间排序,不要按文件名猜;第三,gzip 失败不要让整个脚本退出,否则后面的清理也不会跑。
磁盘阈值告警
usage=$(df -P / | awk 'NR==2 {gsub(/%/"",$5); print $5}')
if [ "$usage" -ge 80 ]; then
echo "磁盘使用率已达 ${usage}%" | logger -t log-rotate
fi
把阈值检查和轮转放在同一个定时任务里容易互相掩盖:轮转失败时告警仍应发出。建议用两个 cron 条目,一个做轮转,一个只做检查;告警通道可以先用系统日志和邮件占位,等有统一告警平台再接 webhook,不要在脚本里硬编码敏感信息。
定时与验证
0 0 * * * /usr/local/bin/rotate-app-log.sh
*/30 * * * * /usr/local/bin/check-disk.sh
上线前先在测试目录跑三遍:空目录、已有旧日志、磁盘模拟高占用。重点验证:正在写入的日志没有丢行;压缩包能正常解开;保留期外的文件确实被删;脚本在 set -e 下不会因为 find 没有匹配而提前退出。
常见坑
- 只按日期切,不按大小切:突发流量一天就能写满磁盘。
- 删日志不重启应用:句柄还指向已删除文件,磁盘空间不释放。
- 保留期写在脚本外:换人维护时没人知道为什么是 14 天。
- 告警只发一次:磁盘持续上涨时,至少每小时重复提醒一次。
把轮转、清理、告警拆成三个小脚本,出了问题可以单独停掉其中一个,这比一个什么都管的大脚本更耐用。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)