Ubuntu 服务器磁盘空间异常增长的排查指南
Ubuntu Server(尤其是 24.04 LTS / 26.04 LTS)磁盘空间异常增长是生产环境中最常见的告警之一。 异常增长通常不是“突然爆炸”,而是某个子系统持续、隐蔽地积累数据,最终突破阈值。理解背后的机制和增长模型,比记住一堆清理命令更重要。
1. 磁盘空间增长的理论模型与常见分类
Linux 文件系统(ext4/xfs/btrfs)空间消耗可以分为三类:
- 静态消耗:系统、软件包、内核(相对稳定,增长慢)
- 可预测增长:日志、缓存、临时文件(线性或指数增长,受负载/配置影响)
- 突发/失控增长:bug、配置错误、恶意行为导致的无限写入(最危险)
2025–2026 年 Ubuntu Server 上最常见的“异常增长源”按频率排序:
- systemd-journald 日志(最常见,持久化后特别明显) 默认 volatile(内存),但生产环境几乎都启用 persistent(/var/log/journal)。 无 vacuum 配置时,按大小/时间无限增长,尤其在高负载服务(nginx、mysql、docker)下每天几百 MB 到 GB 级。
- Docker / 容器相关(overlay2、container logs、build cache、images) /var/lib/docker 目录下:overlay2(存储层)、containers/*-json.log(无限制日志)、buildkit/tmp、images/prune 未清理。
- APT 包缓存(/var/cache/apt/archives) unattended-upgrades 或手动 upgrade 后旧 .deb 未清理,累积几十 GB。
- Snap 包(/var/lib/snapd/snaps) Snap 自动保留多个修订版(默认 3–5 个),每个修订版几百 MB 到 GB,更新频繁的应用(如 core、firefox)特别明显。
- 应用日志(/var/log/nginx、/var/log/mysql、自定义服务) 无 logrotate 或配置错误(如 debug 级别、无 rotation)导致单个 .log 文件无限增长。
- 临时文件 /tmp、/var/tmp 重启不清空、程序异常退出未清理、构建脚本写中间文件。
- 旧内核(/boot) 自动更新保留多个内核,占用几百 MB 到 1–2 GB。
- 已删除但进程持有的文件(deleted but open) 文件被 rm,但进程仍持有 fd,导致空间未释放(df 显示满,du 显示少)。
- inode 耗尽(非空间,而是元数据满) 小文件爆炸(如邮件队列、临时 session 文件),df -i 显示 100%。
2. 分层排查逻辑(从表象到根因)
步骤 1:全局概览(先区分空间 vs inode)
使用 df -hT 和 df -i 同时看。
- 空间满但 inode 正常 → 大文件在增长
- inode 满但空间有余 → 海量小文件(常见于 /tmp、/var/spool/postfix、数据库 tmp)
步骤 2:定位占用大户目录(分治法)
从根开始逐级缩小范围。 常见前三名:/var(日志+缓存+docker+数据库)、/home(用户数据)、/usr(snap/flatpak)。
步骤 3:针对性深挖高嫌疑目录
- /var/log 或 journal journald 持久化后无限制增长是头号嫌疑。 大日志文件往往是循环错误(反复重试、权限问题、debug 模式)导致。
- /var/lib/docker Docker 默认不限制日志大小、无自动 prune。 build cache、dangling images、dead containers 累积极快。
- /var/cache/apt 未运行 autoremove/autoclean 时积累旧包。
- /var/lib/snapd/snaps Snap 修订版保留机制(可配置保留数量)。
- 已删但未释放 进程持有已删除文件 fd 是“df 满 du 少”的经典原因。
步骤 4:根因分析(为什么会持续增长)
- 日志类:logrotate 配置缺失/失效、journald 无 vacuum、应用 debug 级别未关。
- Docker:无 log-opts(max-size)、未定期 prune。
- Snap:自动刷新 + 高保留数。
- 临时文件:程序 bug 或 cron 任务异常。
3. 生产环境常见误区与理论陷阱
- 误区1:只看 du -sh /* 没看到 /var/log/journal → journal 是二进制,不显示在 du 中(需 journalctl –disk-usage)。
- 误区2:rm 大日志后空间没释放 → 进程仍持有 fd(需重启服务或 kill 进程)。
- 误区3:清理 /tmp 后又满 → 程序在运行时写临时文件,重启不清空(tmpfs 除外)。
- 误区4:以为 snap/flatpak 不占空间 → 每个修订版都是完整副本。
- 陷阱:ext4 默认保留 5% 给 root,df 显示 100% 但 root 还能写(非 root 用户先报错)。
4. 预防与长期治理建议(2026 年视角)
- journald:配置 Storage=persistent + SystemMaxUse=2G–5G + SystemMaxFileSize=500M
- Docker:daemon.json 设置 log-driver json-file + max-size: “10m” + max-file: “3”;定期 docker system prune -a –volumes
- APT:unattended-upgrades + 定期 apt autoremove –purge && apt autoclean
- Snap:snap set system refresh.retain=2;定期 snap list –all | grep disabled | xargs snap remove
- logrotate:所有自定义服务强制配置 rotation + compress
- 监控:Netdata/Prometheus + node_exporter 监控 /var/log/journal 大小、/var/lib/docker 使用率、inode 使用率
- 告警:磁盘使用 >80%、inode >80%、journal >1G 时告警
磁盘空间异常增长本质上是“某个子系统无限制写入”的表现。 找到持续写入的源头(日志、缓存、容器),理解其增长模型并配置上限/清理策略,是根治的关键。