当服务器磁盘空间不足时,首先要排查的就是哪个文件夹(目录)真正占用了存储。du -sh /path 是最常用的命令,它会以人类可读的格式打印该路径的总磁盘占用。在 Linux 中,“文件夹”与“目录”含义相同,因此下文命令对两者都适用。

如果使用 ls -l,目录通常显示为 4096 字节,但该数值仅代表目录的元数据,而非其下文件的大小。du(disk usage,磁盘占用)命令才会显示文件和目录实际占用的空间。本指南将介绍如何使用 du 及相关命令来查看大小、定位大目录并管理磁盘空间。

使用 du 查看目录大小

要以人类可读的格式显示目录的总大小,可结合使用 -s(summarize,仅汇总)与 -h(human-readable,人类可读)选项:

sudo du -sh /var
85G /var
  • -s:只显示总大小,不逐一列出每个子目录
  • -h:以人类可读的格式(K、M、G)打印大小

该命令使用 sudo,是因为 /var 下的许多文件归 root 所有。若不使用 sudodu 对无法访问的路径会打印 “cannot read directory”(无法读取目录)警告。

查看单个文件的大小

要查看单个文件的大小,将文件路径传给 du 即可:

du -sh /var/log/syslog
12M /var/log/syslog

也可以使用 ls -lh 在查看其它元数据的同时看到文件大小:

ls -lh /var/log/syslog
-rw-r----- 1 syslog adm 12M Feb 13 10:00 /var/log/syslog

如需包含精确字节数、块大小及 inode 编号的详细文件信息,可使用 stat

stat /var/log/syslog

若只需要字节数,可通过 -c 选项向 stat 传入格式字符串:

stat -c %s /var/log/syslog
12582912

列出各子目录的大小

要查看每个一级子目录占用的空间,可使用 --max-depth 选项:

sudo du -h --max-depth=1 /var
5.0G /var/cache 4.0K /var/empty 4.0K /var/games 77G /var/lib 4.0K /var/local 3.3G /var/log 4.0K /var/opt 196K /var/spool 28K /var/tmp 24K /var/db 85G /var

输出条目按 du 遍历目录的顺序排列,而非按大小排序,且 /var 自身的总计排在最后。若想按大小对子目录排序,可将输出通过管道传给 sort

sudo du -h --max-depth=1 /var | sort -rh

--max-depth 还有简写形式,因此 du -h -d 1 /var 效果相同,在 macOS 和 BSD 上(不支持长格式)需要使用该简写。

也可以结合 -c 选项使用星号通配符,以在末尾附带总计:

sudo du -shc /var/*

-c 标志会在输出末尾添加一行总计。注意,星号通配符不匹配隐藏文件或隐藏目录(即以 . 开头的项)。

若要增加深度、查看两级子目录:

sudo du -h --max-depth=2 /var

找出占用空间最大的目录

要找出占用空间最多的目录,可将 du 的输出通过管道传给 sorthead

sudo du -h /var/ | sort -rh | head -10
85G /var/ 77G /var/lib 75G /var/lib/libvirt/images 75G /var/lib/libvirt 5.0G /var/cache 3.3G /var/log 2.1G /var/cache/apt 1.5G /var/log/journal 196K /var/spool 28K /var/tmp

sort -rh 按人类可读的大小以逆序排序,最大的条目排在前面。head 命令将输出限制在前 10 条结果。

若要在输出中包含单个文件,可加上 -a 标志:

sudo du -ah /var/ | sort -rh | head -10

当逐层深入排查目录时,反复使用 dusort 会相当繁琐。ncdu(NCurses Disk Usage)工具会扫描指定路径并以交互方式浏览结果,默认按磁盘占用排序。在 Ubuntu 与 Debian 上用 sudo apt install ncdu 安装,在 Fedora 上用 sudo dnf install ncdu,而在 RHEL 上需先启用 EPEL 仓库再安装。运行 ncdu /var 后,即可用方向键进入占用最大的文件夹。

排除指定目录

要在扫描时跳过特定目录,可使用 --exclude 选项:

sudo du -sh --exclude='*.log' /var

通过重复使用该选项,可以排除多种模式:

sudo du -sh --exclude='cache' --exclude='tmp' /var

当你想测量磁盘占用但又不想计入日志文件、缓存或临时目录时,这非常有用。

表观大小与磁盘占用

默认情况下,du 报告的是文件系统为文件分配的空间,这取决于文件系统的块大小。在 4K 块的文件系统上,一个 1 字节的文件仍会占用 4 KB 磁盘空间。

--apparent-size 选项显示的是文件中实际包含的数据量:

sudo du -sh --apparent-size /var

表观大小是文件包含的字节数;磁盘占用是文件系统实际分配的空间。对于包含大量小文件的目录,两者可能相差甚远。

在规划传输时,表观大小比分配的磁盘占用更接近文件数据量,但它并非网络流量的精确度量。rsync 只发送变更数据并可压缩,而 scpsftp 会引入协议开销。文件系统差异也可能导致 du 在源端与目标端报告不同的分配大小。

使用 df 查看剩余磁盘空间

du 命令用于测量文件和目录占用的空间,df 命令则显示每个已挂载文件系统剩余的可用空间:

df -h
Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 35G 13G 73% / tmpfs 2.0G 0 2.0G 0% /dev/shm /dev/sdb1 200G 120G 70G 63% /data

当你想知道哪些目录在占用空间时用 du;当你想知道分区还剩多少空间时用 df

故障排查

du: cannot read directory '/path': Permission denied(无法读取目录:权限不足):当前用户对该目录没有读取权限。请使用 sudo 运行 du 以访问所有路径。

du 与 ls 显示的大小不同ls -l 显示的是普通文件的表观字节大小;du 默认显示按块分配的磁盘空间。如需以精确字节数获取表观大小,可使用 du -b filestat -c %s file

du 输出使用块而非人类可读单位:加上 -h 标志即可用 K、M、G 显示大小。不加 -h 时,du 在大多数系统上默认以 1 KB 块为单位。

在大型目录树上 du 运行缓慢du 会读取每一个文件与子目录。可使用 --max-depth=1 限制深度,或用 --exclude 跳过不需要测量的大型目录。

快速参考

如需可打印的快速参考,请参阅 du 速查表。

命令 说明
du -sh /path 目录的总大小
du -sh file.txt 单个文件的大小
du -h --max-depth=1 /path 每个一级子目录的大小
du -h --max-depth=1 /path | sort -rh 按大小排序的子目录
du -shc /path/* 含总计的各子目录大小
du -ah /path | sort -rh | head -10 最大的 10 个条目
du -sh --exclude='*.log' /path 排除匹配模式的文件
du -sh --apparent-size /path 表观大小(而非磁盘占用)
ls -lh file.txt 含元数据的文件大小
stat file.txt 详细的文件信息
stat -c %s file.txt 精确的字节数
df -h 各文件系统的剩余空间

常见问题

du 与 df 有什么区别?du 命令测量特定文件和目录占用的空间;df 命令显示每个已挂载文件系统的总空间、已用空间与可用空间。用 du 找出是什么在占用空间,用 df 查看还剩多少空间。

为什么 du 显示的大小大于文件大小之和?文件系统以固定大小的块(通常为 4 KB)分配空间,一个 1 字节的文件仍会占用一整个块。包含大量小文件的目录,其 du 总计会大于这些文件表观大小之和。

如何找到系统中最大的文件与目录?使用 sudo du -ahx / | sort -rh | head -20 可列出根文件系统上最大的 20 个条目,输出同时包含文件与目录。若只想搜索普通文件,请参阅《在 Linux 中查找大文件》。

du 中的 -s 标志有什么作用?-s(summarize,汇总)标志让 du 只显示指定目录的总大小,而不逐一列出每个子目录。

不使用 sudo 能查看目录大小吗?可以,前提是查看你自己拥有的目录。只有当目录中包含其他用户或 root 拥有的文件时才需要 sudo。不使用 sudo 时,du 会跳过不可读路径并打印权限警告。

总结

需要快速获取总计时使用 du -sh /path;若要定位占用空间的内容,可改用 --max-depthsort -rh。若需查看文件系统级别的剩余空间,则改用 df -h