答案是df与du统计逻辑不同:df读取文件系统超级块元数据,包含已删未释文件、保留空间等;du递归统计可见文件实际大小,故不一致属常态。

直接看 du 和 df 的差异,别只跑一个命令就下结论——df 显示的是文件系统级可用空间,du 统计的是目录内实际文件占用,两者不一致是常态,不是“不准”。
df 显示空间已满但 du 加起来远小于总量?
这是最常被误判的场景。根本原因通常是:已删除但仍有进程打开的文件(unlinked but open)仍占磁盘空间,df 会计入,du 找不到路径自然不统计。
- 查这类“幽灵文件”:
lsof +L1(+L1 表示 link count 为 0),重点关注DEL标记的条目 - 确认某进程是否正占用已删文件:
lsof -p <pid> | grep deleted</pid> - 释放空间只需重启对应进程,或等其自然关闭文件描述符
- 注意:
df的Avail列才是真实可写空间,Used包含保留块(如 ext4 默认 5% reserved for root),普通用户即使看到 95% used,也可能因 reserved 导致写入失败
du -sh * 为什么总和 ≠ du -sh .?
因为 du 默认跳过硬链接重复计数,但统计方式受选项影响极大。
-
du -sh *对每个子项单独计算,各自包含其硬链接指向的内容(若存在) -
du -sh .在目录内去重统计,同一 inode 只算一次 - 想严格按文件实体统计(避免硬链接干扰):用
du -sh --apparent-size,它按文件逻辑大小而非磁盘占用 - 排查隐藏大文件(包括点文件):加
-a参数,du -sh .[^.]* * 2>/dev/null | sort -h
如何准确定位大目录而不被缓存/权限干扰?
du 执行时受 I/O 缓存、读取权限、符号链接循环影响,容易卡顿或漏报。
- 绕过权限拒绝:
sudo du -shx /path 2>/dev/null(-x不跨文件系统,2>/dev/null屏蔽 Permission denied) - 加速大目录扫描:
du -sh --max-depth=1 /path | sort -h,比递归du -sh *更稳 - 排除常见干扰项(如容器 overlay、日志归档):
du -sh --exclude='/var/lib/docker' --exclude='/var/log/journal' / - 真正“深度”分析需结合
ncdu(交互式,支持鼠标和树形展开),安装后直接ncdu /,按d可删除选中项
真正麻烦的从来不是命令怎么敲,而是理解 df 看的是块设备层、du 看的是文件层、而内核还留着未释放的 deleted 文件——三者视角不同,必须交叉验证才能定位真实瓶颈。











