df 命令详解:全称、常用参数与输出各列含义
df 命令是 disk free 的缩写,用来查看每个已挂载文件系统的总容量、已用空间、可用空间和使用率。日常用 df -h 看空间,df -i 看 inode,df -hT 顺带显示文件系统类型;巡检时不能只看百分比,还要看剩余的绝对空间和增长速度。
df 命令是 disk free 的缩写,字面意思是“磁盘剩余空间”,属于 GNU coreutils,几乎所有 Linux 发行版都自带。它的作用是列出每个已挂载的文件系统用了多少、还剩多少。最常用的写法是 df -h,-h 让大小以 K、M、G、T 显示:
df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 795M 1.6M 793M 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 98G 23G 70G 25% /
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda2 2.0G 185M 1.6G 11% /boot
/dev/sda1 1.1G 6.2M 1.1G 1% /boot/efi
/dev/sdb1 3.6T 2.9T 532G 85% /data
tmpfs 795M 12K 795M 1% /run/user/1000
这是一台 Ubuntu 服务器的示例输出:根分区在 LVM 逻辑卷上,用了 25%;数据盘挂在 /data,用了 85%,还剩 532G。
df 是什么的缩写,能看什么、看不到什么
名字虽然叫 disk free,df 统计的其实是文件系统的空间,而不是物理硬盘。它不逐个统计文件,而是直接读取文件系统自己维护的计数,所以即使是几十 TB 的分区也能瞬间出结果。也正因为如此,它只能看到已经挂载的文件系统:插上了但没挂载的硬盘、没格式化的分区,df 里都不会出现。几个容易混用的命令分工如下:
| 想知道什么 | 用哪个命令 |
|---|---|
| 每个分区总共多大、用了多少、还剩多少 | df -h |
| 某个目录占了多少空间 | du -sh 目录 |
| 机器上有几块盘、怎么分区,包括没挂载的 | lsblk |
| 某个分区以什么参数挂载,是不是只读 | findmnt 挂载点 |
输出各列是什么意思
| 列名 | 含义 | 看的时候注意 |
|---|---|---|
| Filesystem | 文件系统的来源 | /dev/sda2 是普通分区;/dev/mapper/ubuntu--vg-ubuntu--lv 是 LVM 逻辑卷,名字里的 -- 代表卷组名、逻辑卷名中的一个 -,即卷组 ubuntu-vg 下的逻辑卷 ubuntu-lv;tmpfs 是内存盘;overlay 是容器的文件系统 |
| Size | 文件系统总容量 | 是格式化后的容量,不是硬盘的标称容量,见后文 |
| Used | 已用空间 | — |
| Avail | 普通用户还能用的空间 | 不包括为 root 预留的部分 |
| Use% | 使用率 | 计算公式是 Used ÷(Used + Avail),小数部分一律进位 |
| Mounted on | 挂载点 | 判断某个目录落在哪个分区上 |
拿上面根分区那一行验算一遍:23 + 70 = 93G,比 Size 的 98G 少了约 5G。这部分既不算已用,也不算可用,是 ext4 默认为 root 预留的 5% 空间(98G × 5% ≈ 4.9G),用来保证分区写满时 root 还能登录处理。使用率按 23 ÷ (23 + 70) ≈ 24.7% 计算,进位后显示为 25%。-h 显示的数字都经过取整,这样验算只能看个大概,要精确核对就用 df -k 看以 KB 为单位的原始数值。因为分母不含预留空间,所以 Use% 显示 100% 时,普通用户已经写不进去,root 却还能写。
这个预留在根分区上很有用,在大容量数据盘上就有点浪费:3.6T 的 /data 按 5% 算,预留了 180G 左右。纯数据分区可以把比例调低,例如改成 1%:
sudo tune2fs -l /dev/sdb1 | grep -i 'reserved block count' # 查看当前预留的块数
sudo tune2fs -m 1 /dev/sdb1 # 预留比例改为 1%,在线生效
XFS 没有这种为 root 预留的空间,同样的算式在 XFS 分区上,Used 加 Avail 基本等于 Size。根分区建议保持默认,不要改。
df 命令常用参数
| 参数 | 作用 | 示例 |
|---|---|---|
-h |
自动选择单位,按 1024 进位 | df -h |
-H(--si) |
自动选择单位,按 1000 进位,与硬盘标称容量的口径一致 | df -H |
-k、-BM、-BG |
固定以 1024 进位的 K、M、G 为单位输出,便于比较和计算 | df -BG /data |
-T |
增加 Type 列,显示 ext4、xfs、tmpfs 等类型 | df -hT |
-t 类型 |
只显示指定类型,可以写多次 | df -h -t ext4 -t xfs |
-x 类型 |
排除指定类型,可以写多次 | df -h -x tmpfs -x devtmpfs |
-i |
显示 inode 的用量,而不是空间 | df -i |
-l |
只显示本地文件系统,跳过 NFS 等网络挂载 | df -hl |
-a |
连同 proc、sysfs 这类伪文件系统和重复的挂载一起显示 | df -a |
-P |
按 POSIX 规定的格式输出,列固定,老脚本常用 | df -P |
--output=字段 |
自己挑选要显示的列 | 见下方示例 |
--total |
在末尾加一行合计 | df -h --total -x tmpfs |
| 路径 | 只显示这个路径所在的文件系统 | df -h /var/lib/mysql |
几个实际用得上的组合:
# 只看真实磁盘:排除内存盘、容器层和 snap 软件包的只读镜像
df -hT -x tmpfs -x devtmpfs -x overlay -x squashfs
# 数据库目录在哪个分区上、还剩多少
df -h /var/lib/mysql
# 空间和 inode 使用率放在一张表里
df -h --output=source,fstype,size,used,avail,pcent,ipcent,target -x tmpfs -x devtmpfs
# 脚本里取根分区的可用空间,单位 KB
df -P / | awk 'NR==2 {print $4}'
--output 不能和 -i、-T、-P 同时使用,否则会报两个选项互斥;要 inode 和类型,就把 ipcent、fstype 写进字段列表里。可用的字段有 source、fstype、itotal、iused、iavail、ipcent、size、used、avail、pcent、file、target。
df -i:inode 怎么看
每个文件和目录都要占用一个 inode。ext4 的 inode 总数在格式化时就定死了,小文件特别多的分区,可能空间还剩一大半,inode 却先用完,这时写文件同样报 No space left on device。df -i 的输出:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/ubuntu--vg-ubuntu--lv 6553600 245872 6307728 4% /
/dev/sda2 131072 623 130449 1% /boot
/dev/sda1 0 0 0 - /boot/efi
/dev/sdb1 244187136 101245 244085891 1% /data
| 列名 | 含义 |
|---|---|
| Inodes | inode 总数 |
| IUsed | 已用的 inode,约等于这个分区上文件和目录的总数 |
| IFree | 剩余可用的 inode |
| IUse% | inode 使用率 |
/boot/efi 显示 0 和 - 是正常的,它是 FAT 格式的 EFI 分区,不使用 inode 机制。根分区的 6553600 个 inode,是 ext4 在常见大小(4 TiB 以下)的分区上默认每 16 KB 空间分配一个 inode 的结果。如果事先知道某个分区要存海量小文件(比如图片缓存、邮件存储),格式化时就可以加大 inode 数量:mkfs.ext4 -i 8192 /dev/sdc1 表示每 8 KB 分配一个,-N 参数则直接指定 inode 总数。XFS 的 inode 按需分配,一般不会先于空间用尽。
巡检时看 df:关注哪些阈值
只看 Use% 容易误判:同样是 85%,20G 的根分区只剩 3G 左右,一个失控的日志几个小时就能写满;20T 的数据盘还剩 3T,可能够用几个月。所以巡检时按分区的用途分别看:
| 挂载点 | 为什么要盯 | 参考阈值(按业务调整) |
|---|---|---|
/ |
写满后日志写不进、服务异常,严重时无法登录 | 80% 预警,90% 必须处理 |
/boot |
分区小,满了以后新内核装不上,apt 升级报错 | 80%,或可用空间少于 300M |
/var、/var/log(单独分区时) |
日志、数据库、容器镜像都在这里增长 | 80% 预警,90% 处理 |
数据盘(如 /data) |
容量大,百分比不敏感 | 按增长速度算剩余天数,少于 30 天就扩容或清理 |
/dev/shm、/run 等 tmpfs |
占的是内存,不是磁盘 | 持续增长就查是哪个程序写的 |
| 所有分区的 IUse% | 会话文件、缓存、邮件队列等小文件堆积 | 80% |
剩余天数的算法:假设 /data 一周前已用 2.8T,今天 2.9T,一周增长约 100G,每天约 15G;还剩 532G,532 ÷ 15 ≈ 35 天。超过 30 天的余量,留出了采购硬盘、安排上架的时间。
把检查写成脚本,只输出超过阈值的分区,没有输出就说明一切正常:
#!/bin/bash
# 列出空间或 inode 使用率达到阈值的文件系统
LIMIT=80
timeout 10 df -h --output=target,pcent,ipcent,avail \
-x tmpfs -x devtmpfs -x overlay -x squashfs \
| awk -v limit="$LIMIT" 'NR==1 || $2+0 >= limit || $3+0 >= limit'
awk 里的 $2+0 会把 85% 这样的字符串转成数字 85,- 会被当成 0。timeout 10 防止遇到失联的网络挂载时脚本一直卡住。另外,df 不会告诉你哪个分区变成了只读,磁盘出错后内核把分区自动改成只读的情况,巡检时用 findmnt -O ro -t ext4,xfs 单独查一遍,有输出就要看看是不是该只读的。
几个看起来不对的 df 输出
- 买的是 4 TB 硬盘,df 只显示 3.6T。硬盘厂商按 1000 进位,4 TB 约等于 4×10¹² 字节;
df -h按 1024 进位,换算下来只有约 3.64 TiB,再扣掉格式化时 inode 表、日志等元数据占用的空间,就是 3.6T 左右。用df -H看会更接近标称值。 - 一串
/dev/loop开头的设备,使用率全是 100%。装过 snap 软件的 Ubuntu 上常见,它们是 snap 软件包的只读镜像(squashfs 格式),本来就是满的,加-x squashfs隐藏即可。 - 装了 Docker 后多出很多 overlay。每个运行中的容器都有一个 overlay 挂载点,显示的容量和使用率与
/var/lib/docker所在的分区完全相同,它们是同一块空间的不同视图,不是额外的空间,加-x overlay隐藏。 - tmpfs 的 Size 加起来超过了内存。tmpfs 的 Size 只是上限,实际只占已写入内容那么多的内存,几个 tmpfs 的上限加起来超过物理内存并不矛盾。
在管理系统里怎么落地
df 只回答“挂上去的空间用了多少”,回答不了“这台机器一共有几块盘”。巡检中常见的一种浪费是:客户加购的数据盘装上了,却一直没分区挂载,df 里看不到,lsblk 里却躺着一块 3.6T 的 sdc。单台机器上用 lsblk -dno NAME,SIZE,MODEL 列出所有物理盘,再和 df 里出现的设备对照就能发现。
机器一多,靠登录逐台对照就不现实了。Toplink DCIM 的机柜与资产通过下发到服务器的采集脚本拿到真实的硬盘、CPU 和内存信息,每一次采集结果都存档;台账里人工登记的配置与实际探测到的配置并列保存。df 负责看使用率,资产台账负责看硬件配置,两边对照,就能找出有盘没用、配置被改过或者硬盘被换过的机器。
常见问题
df 和 du 有什么区别?
df 直接向文件系统要统计数字,几乎瞬间出结果,看的是整个分区;du 逐个遍历文件累加大小,看的是某个目录。两者对不上时,最常见的原因是文件已被删除但仍有进程打开着,用 lsof +L1 可以找出来。
df 命令卡住不动怎么办?
多半是挂着一个已经失联的 NFS 等网络文件系统,df 在等它响应。按 Ctrl+C 中断后,用 df -hl 只看本地文件系统,或者用 timeout 10 df -h 限定等待时间,再用 findmnt -t nfs,nfs4 找出是哪个挂载点出了问题。
Windows 上有 df 命令吗?
没有。PowerShell 里用 Get-Volume 可以看到每个卷的总容量(Size)和剩余空间(SizeRemaining),用 Get-PSDrive -PSProvider FileSystem 也能看到各盘的已用和可用空间。