这个场景解决什么
df 说已用 80%,du 从根目录挨个加起来却只有 40%,两套数字差了一倍。这不是工具算错,而是口径不同:df 按文件系统统计块的分配情况,du 按目录树累加文件占用的块。差异通常来自五类原因——已删除但仍被进程持有的文件、被挂载点盖住的目录、稀疏文件与硬链接、LVM 快照、以及文件系统给 root 预留的块。按固定顺序排查,十分钟内能定位到真凶。
基本信息
| 适用场景 | 容量统计对不上、磁盘莫名变满、清理后空间没释放 |
|---|---|
| 目标 | 找出隐藏占用并解释两套数字的差异 |
| 工具链 | df、du、lsof +L1、findmnt -A、ls -lsh、lvs、tune2fs |
| 判断前提 | du 加 -x 才是同一文件系统口径,否则数字不可比 |
典型使用场景
- 删了大日志空间没释放:进程还持有已删除文件的句柄,df 不变而 du 找不到对象
- 容量监控告警与人工核查不符:报表按 du 统计,监控按 df 口径,需要解释差在哪
- 目录被挂载点盖住:先在目录里写了数据,之后又在其上挂载了设备,旧数据成了不可见占用
- 快照吃掉空间:LVM 或存储快照随时间增长,df 看得到但 du 看不到
- 排查前先对齐口径:确认两套命令是否跨文件系统、是否含预留块,避免在假差异上浪费时间
五项差异源依次排查
五项差异源依次排查
# 1) 已删除但仍被打开的句柄(最常见的元凶)
lsof +L1 | head -20
# 2) 被挂载点盖住的目录(overmount)
findmnt -A / | head -20
# 3) 稀疏文件:ls -s 是实际占用,ls -l 是逻辑大小
find /data -type f -size +1G -exec ls -lsh {} \; | awk '{print $1,$2,$10}' | head
# 4) LVM 快照占用
lvs -o lv_name,size,data_percent,snap_percent 2>/dev/null
# 5) 同一文件系统的口径对齐后再比
umount /mnt/probe 2>/dev/null; du -xsh /data; df -h /data口径对齐与硬链接复核
口径对齐与硬链接复核
du -xsh /data # -x 不跨文件系统,与 df 同口径
du -sh --apparent-size /data # 逻辑大小(含稀疏空洞),一般比实际占用大
du -sl /data | tail -1 # -l 重复统计硬链接,看硬链接造成的差异
tune2fs -l /dev/vg0/data | grep -E 'Reserved block count|Block count'差异源特征对照
| 差异源 | 典型特征 | 验证手段 |
|---|---|---|
| 已删除句柄 | df 不变,du 找不到对应文件 | lsof +L1 看 deleted 行 |
| 被覆盖目录 | du 某目录偏小,进去看不到东西 | findmnt -A 找同路径两次挂载 |
| 稀疏文件 | ls -l 很大但 ls -s 很小 | du 与 --apparent-size 对比 |
| 硬链接 | du 数字比实际目录内容小 | du -l 与默认结果对比 |
| 快照与预留块 | df 显示偏满,du 无对应文件 | lvs、tune2fs 查预留块数量 |
ext4 默认给 root 预留 5% 的空间,df 的 Avail 会直接少掉这块,看起来比 du 口径更满。数据盘不需要给 root 留这么多时可用 tune2fs -m 1 调整,改完用 dumpe2fs 复核。
LVM 快照写满会导致快照失效,同时原卷空间出现异常增长。给快照配置独立的容量与使用率监控,比事后排查便宜得多。