当前位置:首页>Linux>每天学一个Linux命令系列(18):du - 找出吃磁盘的元凶,精准定位大文件

每天学一个Linux命令系列(18):du - 找出吃磁盘的元凶,精准定位大文件

  • 2026-10-11 06:20:56
每天学一个Linux命令系列(18):du - 找出吃磁盘的元凶,精准定位大文件
运
运维少年 · 科技观察

这个命令是干啥的

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。

E N D

运维少年 · 科技观察

最新文章

随机文章