小型 Linux 服务器一旦把 Docker、Web 服务和 MySQL 都放在同一块系统盘上,磁盘告警往往不是“业务数据突然暴涨”,而是**多个没有上限的运行文件叠在一起**。更危险的操作是为了腾空间直接 rm 业务目录或 MySQL 文件——表面上能立刻降下来,却可能打断复制、备份或恢复链。
本文整理一次 56GB 系统盘排障的顺序:先定位增长源,再给 journal、Web/Docker 日志和 binlog 设可验证上限,最后用周检命令防复发。
一次实际排查的结论
那次根分区使用率约 74%。主要增长项大致是:
| 类别 | 典型位置 | 风险 | 处理原则 |
| — | — | — | — |
| systemd Journal | /var/log/journal | 默认可长期增长 | 设容量上限,再清理历史日志 |
| Web 访问/错误日志 | Nginx、OpenResty 日志目录 | 异常请求或错误循环会快速膨胀 | 按大小与日期轮转、压缩、限份数 |
| Docker JSON 日志 | /var/lib/docker/containers/*/*-json.log | 单个容器可无上限写入 | 已有日志做轮转;新容器配 Docker 日志策略 |
| 未使用镜像 | Docker image store | 反复构建、部署后累积 | 只清理未被容器引用的镜像 |
| MySQL binlog | MySQL 数据目录 | 未设过期会持续增长 | 先确认备份与复制依赖,再用官方命令过期/清理 |
| 业务数据与缓存 | 应用数据、对象存储、构建缓存 | 直接删除可能破坏业务 | 先区分可再生缓存与真实数据 |
清理并加上日志上限后,使用率大约从 74% 降到 56%。核心不是“偶尔清一次”,而是**每个可无限写入的目录都有容量边界**。
排查顺序
先看文件系统和 inode,避免只盯容量却漏掉 inode 耗尽:
df -h
df -i
再按目录找大头;根目录扫描要排除伪文件系统:
du -xhd1 / 2>/dev/null | sort -h
du -xhd1 /var /opt 2>/dev/null | sort -h
日志与 Docker 单独确认:
journalctl --disk-usage
find /var/lib/docker/containers -name '*-json.log' -printf '%s %p\n' 2>/dev/null | sort -n | tail
docker system df
MySQL binlog **不要用 rm 判断或删除**。先在 MySQL 里确认当前日志、复制状态、备份保留要求和自动过期配置;只有确认旧日志不再被复制或恢复依赖后,才使用 PURGE BINARY LOGS 或 binlog 过期设置。
已验证的日志限额策略
systemd Journal
为 journald 建独立配置片段,例如 /etc/systemd/journald.conf.d/90-disk-cap.conf:
[Journal]
SystemMaxUse=512M
SystemKeepFree=1G
RuntimeMaxUse=128M
含义:持久化系统日志最多约 512MB;至少预留 1GB 空闲;运行时日志最多 128MB。对小型单机排查近期重启、服务异常和登录事件通常够用。
修改后重启 journald,并只 vacuum 到目标上限:
systemctl restart systemd-journald
journalctl --vacuum-size=512M
journalctl --disk-usage
如果服务器承担高频审计、长周期排障或合规留痕,应提高上限,或把日志送到专门的日志系统,不要机械套 512MB。
Web 与 Docker 日志
用 logrotate 对 Web 日志和现有 Docker JSON 日志做按日检查、超过 50MB 再轮转、压缩并保留有限份数。例如:Web 日志保留 14 份,Docker 日志保留 7 份。
copytruncate 适合不能方便重启的持续写入进程:先复制归档再截断原文件。代价是轮转瞬间可能丢极少量子日志;高审计服务应改成应用 reopen 日志文件。
校验配置:
logrotate -d /etc/logrotate.conf
systemctl status logrotate.timer
新建 Docker 容器更稳妥的做法,是在 daemon 或 Compose 里给 json-file 配置 max-size、max-file,让 Docker 自己限制每容器日志。外部 logrotate 可以兜底旧容器,但不是新部署的唯一防线。
哪些东西不能直接删
| 内容 | 为什么不能直接删 | 安全做法 |
| — | — | — |
| MySQL binlog | 可能影响复制、时间点恢复或备份链 | 检查依赖后用 PURGE BINARY LOGS 或自动过期 |
| 对象存储文件 | 多为用户上传或业务素材 | 走业务生命周期、备份与回收站 |
| 构建缓存、依赖缓存、模型文件 | 有些可再生,有些重建成本高 | 先识别再清理或迁移 |
| Docker 卷 | 可能保存数据库与业务状态 | 确认挂载容器与备份后再处理 |
防复发清单
- journald、Web、应用、Docker 日志都有上限。
- 每周检查:
df -h、journalctl --disk-usage、docker system df、MySQL binlog 保留状态。 - 根分区 80% 提醒,90% 视为立即处理事件。
- 告警不只看磁盘,也看错误日志速率——日志暴涨常是业务异常、爬虫或配置循环。
- 新服务上线前确认:日志位置、轮转策略、数据备份与保留周期。
- 留下清理记录:何时清、清了什么、是否影响容器/数据库、清后剩余空间。
最小巡检命令集
df -h /
journalctl --disk-usage
docker system df
du -xhd1 /var /opt 2>/dev/null | sort -h | tail -30
脚本适合发现和告警;涉及 binlog、Docker 卷、对象存储与业务数据的清理,仍应保留明确确认步骤。
—
来源笔记:30-技术/工程排障/Linux服务器-磁盘占满排障与防复发.md




