df 与 du 结果不一致是正常现象,因 df 统计文件系统元数据空闲块,du 遍历目录累加文件实际占用块;常见原因包括已删但未释放的文件、嵌套挂载、配额/快照机制及 inode 耗尽。

df 显示的“可用空间”和 du 统计的“已用空间”对不上怎么办
这是最常被误认为是 bug 的现象,其实两者根本不是同一套统计逻辑。df 读的是文件系统元数据(比如超级块里的空闲块数),而 du 是遍历目录树、累加每个文件的磁盘占用块数。当出现差异时,优先怀疑三类情况:
- 有进程仍在使用已被
rm删除的文件:这类文件在du中不可见,但df仍将其计入“已用”,用lsof +L1可查出(+L1 表示 link count = 0 的打开文件) - 挂载点下存在其他文件系统(比如 bind mount 或子卷),
df按挂载点归属统计,du却会递归进入并重复计算 - 文件系统启用了配额(quota)或快照(如 btrfs snapshot),
df显示的是配额限制下的视图,du不感知这些策略
用 df -h 和 df -i 一起看,才能判断写不进文件的真实原因
磁盘明明还有几十 GB 空间,却提示 No space left on device,大概率是 inode 耗尽了。Linux 分区格式化时就固定了 inode 总量,小文件多(比如日志、缓存、邮件碎片)极易占满它。
-
df -h关注Use%和Avail列,确认块级空间是否真的紧张 -
df -i关注IUse%列,若接近 100%,说明 inode 不够用,此时删大文件没用,得清理海量小文件(比如find /var/log -name "*.log.*" -mtime +30 -delete) - 注意:tmpfs 类型(如
/dev/shm、/run)也受df -i约束,它们的 inode 是内存动态分配的,但总量仍有限
du -sh * | sort -rh 这类管道组合为什么有时卡住或结果不准
直接在根目录或大型目录(如 /var/lib/docker)下执行 du -sh * 容易出问题,不是命令写错,而是路径展开和权限导致的隐性失败。
-
*展开依赖 shell,遇到含空格、换行或特殊字符的目录名会断裂;更安全的写法是find . -maxdepth 1 -mindepth 1 -print0 | xargs -0 du -sh | sort -rh - 某些子目录无读取权限(如
/root、/proc下部分目录),du会报错并跳过,导致总和偏小;加2>/dev/null可抑制错误输出,但要清楚自己忽略了哪些路径 -
sort -rh中的-h依赖 locale 设置,某些最小化系统(如 Alpine)默认不支持,会按字符串排序(10G排在2G前面),此时应改用sort -V或先转成字节数再排
du 默认单位是 KB,但 du -sh 和 ls -lh 显示的大小经常不一致
这不是 bug,是底层存储机制决定的:du 统计的是实际占用的磁盘块(block),而 ls 显示的是文件逻辑大小(size)。一个 1KB 的文件,在 4KB block size 的文件系统上仍占 4KB 磁盘空间。
-
ls -lh file→ 显示文件内容长度,单位是字节(1.3K 表示 1331 字节) -
du -h file→ 显示该文件实际占了多少个 block,四舍五入到最近的人类可读单位(4K 表示它占了 1 个 4KB block) - 想看精确 block 占用,用
du -B1 file(以 byte 为单位输出)或stat file查看Blocks:字段 - 注意:稀疏文件(sparse file)会让
du显示远小于ls的值,因为未写入的 block 不实际分配
真正容易被忽略的是:df 和 du 都不反映文件系统预留空间(reserved blocks),比如 ext4 默认保留 5% 给 root 用户。这部分空间在 df 的 Avail 里已扣除,但普通用户看不到它为何“少了一块”。如果需要让非 root 用户也能用上这部分空间,得用 tune2fs -m 0 /dev/xxx 调整,但不建议在生产系统随意改动。











