这个命令是干啥的
du 的全称是 disk usage(磁盘使用)。和 df 看整个分区不同,du 是 看某个目录或文件在磁盘上占了多少空间。
简单说:df 告诉你还有多少空间,du 告诉你空间被谁吃了。
我第一次被 du 惊艳到是有一次线上磁盘爆满,所有人都在猜是哪个目录的问题。我敲了个 du -sh /*,一秒就锁定了 /data 目录占了 80%,进去又跑了个 du -sh /data/*,发现是日志文件把磁盘塞满了。前后不到一分钟就找到元凶,同事们都惊呆了。
从那以后,排查磁盘满的问题,我都是 du 一路追查下去,比靠猜快太多了。
基本用法(3分钟上手)
du -sh:看目录总大小
# 查看当前目录的总大小(不递归展开子目录详情)
du -sh
# 输出示例
2.3G .
其中 -s(summarize)表示只汇总,不列出每个子目录的明细;-h 以 GB/MB/KB 显示。
展开只看一层
# 查看当前目录下一级所有子目录的大小
du -sh *
# 或者用--max-depth=1(更标准)
du -h --max-depth=1
# 输出示例
12M bin
256K boot
8.0K dev
4.0K etc
1.5G home
...
2.1G usr
1.3G var
查看某个文件的大小
# 直接看文件大小
du -h bigfile.log
# 输出: 456M bigfile.log
进阶骚操作
--max-depth:控制递归深度
这是 du 最实用的参数,可以控制显示到几层目录。
# 只看两层目录
du -h --max-depth=2 /var
# 输出示例
16K /var/lock
4.0K /var/run
124K /var/tmp
1.2G /var/log
456M /var/log/nginx
345M /var/log/mysql
...(等等)
这样一眼就能看出 /var/log/nginx 和 /var/log/mysql 是吃空间的大户。
du -a:列出所有文件
# 默认只显示目录,-a把文件也列出来
du -ah /var/log | head -20
du -c:最后加总
# 分别显示多个目录大小,最后加一行总计
du -ch /var/log /home /tmp
du --exclude:排除不关心的目录
# 排除/proc和/sys(这两个是虚拟文件系统)
du -h --exclude={proc,sys} /
# 排除所有.git目录
du -h --exclude=.git
和 sort 组合:按大小排序
这是排查磁盘问题的核心组合拳。
# 按大小降序排列,找出最占空间的前10个
du -h --max-depth=1 | sort -rh | head -10
# 找超过1G的目录
du -h --max-depth=2 / | sort -rh | grep -E "[0-9]+[.]?[0-9]*G"
sort -rh 的 -h 很重要。没有 -h 的话,sort 会按字典序排序,导致 "2.1G" 排在 "100M" 前面。加上 -h 就能正确识别 K/M/G 后缀按数值排序。
我一开始不知道这个技巧,手动看目录大小,一个一个比较,累死。后来知道 du | sort -rh 这条命令,感觉打开了新世界的大门。
du -t:只显示超过指定大小的目录
# 只看超过100M的目录
du -ht 100M /var
du -d:macOS 上的等效参数
# macOS 不支持 --max-depth,用 -d 代替
du -hd 2
避坑指南
坑1:du 和 ls 看到的大小不一样
ls -lh bigfile.log
# 输出: -rw-r--r-- 1 root root 500M Jun 1 10:00 bigfile.log
du -h bigfile.log
# 输出: 504M bigfile.log
为什么差 4M?因为 ls 显示的是文件逻辑大小,而 du 显示的是磁盘实际占用(包括文件系统的块对齐、间接块等)。稀疏文件差距更大。
坑2:du 会跨挂载点
# 如果不加 -x,du 会穿过挂载点进入其他文件系统
# 比如 /proc 虽然是虚拟的,du 也会进去
du -h --max-depth=1 /
加 -x 参数可以限制只在同一个文件系统中:
# 只在当前文件系统内统计,不穿越挂载点
du -hx /data
坑3:du 跑得慢
目录特别大(比如几百万个小文件)的时候,du 可能要跑很久。
# 只查第一层,先看个大概
du -h --max-depth=1 /large_dir 2>/dev/null
# 也可以跳过某些目录,加快速度
du -h --exclude="*.log" --max-depth=1 /var
坑4:du 和 df 的结果不一致
这个在 df 篇也提过。du 统计的是文件实际占用,但已删除但进程还在打开的文件,df 算空间已用但 du 已经算不到了。所以 df 显示的使用量大于 du 累加的结果是正常的。
实战场景
场景1:磁盘满了,最快的排查流程
磁盘告警来了,我的标准流程:
# 第1步:确认哪个分区满了
df -h
# 第2步:到根分区,看哪个一级目录最大
du -sh /* 2>/dev/null | sort -rh | head -10
# 第3步:锁定大目录,继续深入
du -h --max-depth=1 /var 2>/dev/null | sort -rh | head -10
# 第4步:再深入
du -h --max-depth=1 /var/log 2>/dev/null | sort -rh | head -10
# 第5步:找到大文件了
du -ah /var/log/nginx 2>/dev/null | sort -rh | head -5
整个过程不超过 30 秒,比用 ls -la 一个个目录点进去看快一百倍。
场景2:查找超过 1G 的大文件
# 从根目录出发,找所有超过1G的文件和目录
du -ah / 2>/dev/null | sort -rh | awk '$1 ~ /G/ {print}'
场景3:查看 Docker 容器磁盘占用
# 看Docker整体占用
du -sh /var/lib/docker/
# 看看具体是哪个容器在吃空间
du -h --max-depth=2 /var/lib/docker/containers/ | sort -rh | head -10
场景4:对比 du 和 ncdu
ncdu(NCurses Disk Usage)是 du 的交互式版本。如果你经常做磁盘排查,强烈推荐安装。
# 安装ncdu
apt install ncdu -y # Ubuntu/Debian
yum install ncdu -y # CentOS
# 启动ncdu,交互式浏览目录大小
ncdu /
ncdu 的优势:
1. 交互式界面,上下键浏览,进入子目录
2. 按大小排序一目了然
3. 可以删除不需要的文件
我的经验是:日常快速定位用 du -sh | sort -rh,要深入分析大目录时用 ncdu。
场景5:写个脚本定期检查磁盘
#!/bin/bash
# 每天凌晨统计各项目目录大小,生成报告
REPORT="/var/log/disk_report_$(date +%Y%m%d).txt"
{
echo "磁盘使用报告 - $(date)"
echo "================================"
echo ""
echo "=== 项目目录 ==="
du -sh /data/project*/ 2>/dev/null | sort -rh
echo ""
echo "=== /var 下占用最多的 ==="
du -h --max-depth=1 /var 2>/dev/null | sort -rh | head -10
} > "$REPORT"
echo "报告已生成:$REPORT"
今日作业
假设你的服务器 /data 目录快满了,请写一条 du 命令,完成以下要求:
1. 查看 /data 下一级目录的大小
2. 按从大到小排序
3. 只显示前 5 个最大的目录
4. 用人类可读的格式(K/M/G)
提示:组合使用 du、sort -rh 和 head。