在印度机房用 du 和 find 找大文件,硬链接把统计翻了一倍
上周在孟买那台备份机上遇到一个空间问题:df 显示 /data 用了 87%,但业务那边说这个分区只存了不到 40% 的备份数据。系统是 Ubuntu 20.04,ext4,分区 8T,上面跑的是自己写的增量备份脚本,用 rsnapshot 的思路做的硬链接快照,保留了 14 天的日备。
我先跑了一遍常规的:
du -sh /data/*
du -sh /data/backup/*
结果 /data/backup 报出来 6.4T。但业务侧统计的源数据只有 2T 左右,14 天快照理论上增量不会超过 1T。
我的做法是先用 du 加上 -l 参数排除硬链接干扰,再按目录逐层看:
du -shl /data/backup/*
结果变成 2.8T。差出来的 3.6T 全是硬链接被重复计数——du 默认对同一个 inode 只算一次,但一旦目录被拆开分别统计,同一个 inode 在不同目录下会被各算一遍。我第一次跑 du -sh /data/* 时把 backup 和各天快照目录分开算了,硬链接文件就被重复累加了。
为了确认,我用 find 按 inode 去重验证了一遍:
find /data/backup -type f -printf '%i %s\n' | sort -u -k1,1 | awk '{sum+=$2} END {print sum/1024/1024/1024" GB"}'
结果 2.7T,和 du -shl 基本对得上。
为什么这样做:du 的默认行为和 -l 的行为是两条路径,前者按 inode 去重,后者按目录项计数。硬链接快照场景下,两种统计都“对”,但回答的是不同问题——一个回答“实际占了多少块”,一个回答“每个路径下能看到多少字节”。搞混了就会像我一样,先被 6.4T 吓一跳,再被 2.8T 安慰一下,最后还得用 inode 去重才敢下结论。
哪里会失效:如果备份里有稀疏文件,du 算的是实际块数,find -printf '%s' 算的是逻辑大小,两边会对不上;另外如果目录里有跨文件系统的挂载点,du 不加 -x 会跑出去,统计就不止这个分区了。我自己踩的坑是第一次跑 find 时忘了 -type f,把目录的 inode 也混进去了,数字偏大了一点,虽然不影响结论,但看着别扭。
现在我的习惯是:先 df 看分区,再 du -shl 看目录,最后用 find 按 inode 去重交叉验证,三步对上了才敢删东西。
你们在硬链接快照的场景下,是靠 du -l 还是靠 inode 去重来确认实际占用?有没有遇到过稀疏文件把两边数字拉得很开的情况?
0 条评论
还没有评论,写下第一条。