du -sh * 只显示当前层是因为 * 展开为一级条目,du 会对每个子目录递归计算总大小但仅输出这些项本身;子目录显示的大小已是其全部内容之和,并非元数据体积。

du -sh * 为什么只显示当前层,不递归进子目录?
因为 du 默认只统计显式列出的路径,* 展开后是当前目录下所有**一级条目**(文件和文件夹),但不会自动深入每个子目录内部再汇总——它确实递归计算每个子目录的总大小,但输出时只列出来自 * 的那些项。真正让人困惑的是:你看到的 du -sh * 结果里,某个子目录显示 “4.2G”,这已经是它里面所有内容加起来的大小了,不是它自己的元数据体积。
- 想看更细粒度(比如子目录里哪个子目录占得多),得加
--max-depth=1或手动进到下一层跑du -sh * -
du -sh对软链接默认跳过目标,除非加-L;硬链接只算一次,这是 POSIX 行为,改不了 - 如果某目录显示 size 是 0,大概率是权限不足(
du读不到其内容),不是真为空
排序最占空间的前10个目录,命令怎么写才靠谱?
直接用 du -sh * | sort -hr | head -n 10 看似简洁,但有隐患:当目录名含空格、换行或特殊字符时,sort 会错乱;-h 在部分老系统(如 CentOS 6 的 sort)不支持,会报错。
- 更稳的写法:
du -sh --max-depth=1 ./* 2>/dev/null | sort -k1,1h | tail -n +2 | tail -n 10(tail -n +2排掉.自身那行) - 如果要排除挂载点(比如 /home 下挂了独立磁盘),加
-x参数:du -shx --max-depth=1 ./* -
sort -hr的r是逆序,但某些 locale 下可能让 GB/MB 混排出错,纯 ASCII 排序更可靠
df 显示已用 95%,但 du 加起来才 70%,差那 25% 去哪了?
这不是计算错误,是 Linux 文件系统保留空间 + 已删除但未释放的文件共同导致的。root 用户默认有 5% 预留空间(tune2fs -l /dev/sda1 | grep "Reserved block count" 可查),普通用户看不见这部分,df 却把它算进“已用”;另外,进程打开着一个大文件,然后被 rm 删除,该文件的磁盘块仍被占用,直到进程退出——lsof +L1 能列出这类“已删未释”的文件。
- 查预留空间占比:
tune2fs -l /dev/sda1 | grep "Reserved block count\|Block count",自己算下百分比 - 查被进程锁住的大删除文件:
lsof +L1 / | awk '$7 ~ /[0-9]+[MG]/ {print $7, $9}' | sort -hr | head -5 - 临时释放预留空间(不推荐生产环境):
tune2fs -m 1 /dev/sda1(设为 1%,需 umount 后操作)
想实时监控某个目录增长,有什么轻量办法?
不用上 Prometheus 或 logrotate 分析,watch 配合 du 就够用,关键是避免重复扫描全树影响 IO。建议用 --apparent-size(统计逻辑大小而非磁盘占用)+ --exclude 过滤临时文件,减少抖动。
- 每 5 秒刷新一次某目录总大小:
watch -n 5 'du -sh --apparent-size /var/log' - 排除常见缓存目录加快响应:
du -sh --exclude="*.tmp" --exclude="cache" /opt/app - 注意:
watch默认清屏,加-d可高亮变化项,但别在慢终端(如 tmux 嵌套多层)里开太短间隔,容易卡
实际用的时候,du 的耗时跟目录深度和文件数量强相关,别在 NFS 或 CIFS 挂载点上无脑跑 --max-depth=3,延迟可能超预期。










