用 Shell 脚本给日志做轮转与告警:从磁盘告急到自动清理

举报
yd_291459017 发表于 2026/10/29 11:35:49 2026/10/29
【摘要】 日志写满磁盘是常见故障:本文用 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 没有匹配而提前退出。

常见坑

  1. 只按日期切,不按大小切:突发流量一天就能写满磁盘。
  2. 删日志不重启应用:句柄还指向已删除文件,磁盘空间不释放。
  3. 保留期写在脚本外:换人维护时没人知道为什么是 14 天。
  4. 告警只发一次:磁盘持续上涨时,至少每小时重复提醒一次。

把轮转、清理、告警拆成三个小脚本,出了问题可以单独停掉其中一个,这比一个什么都管的大脚本更耐用。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。