这个命令是干啥的
df 的全称是 disk free(磁盘空闲),用来查看文件系统的磁盘空间占用情况。说人话就是:看磁盘还剩多少空间。
刚学 Linux 的时候,我查磁盘就只会敲 df -h,看一眼有没有满。直到有一次线上告警说"磁盘空间不足",我 df -h 一看还有 20%,心想这不还好好的吗。结果运维老大跑来说:"你看看 inode!"然后我查了 df -i,才发现 inode 已经 100% 了。
从那以后我才知道,磁盘满不只是"空间满了"这一种情况,df 能告诉你的东西远不止这些。
基本用法(3分钟上手)
df:最简陋的查看方式
# 直接敲df,单位是1KB的块
df
# 输出示例(不同系统可能略有差别)
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/vda1 41251136 18936732 20257584 49% /
tmpfs 1000000 500 999950 1% /dev/shm
这个单位看着太痛苦,所以基本没人这么用。
df -h:人类友好格式
# 用GB/MB显示
df -h
# 输出示例
文件系统 容量 已用 可用 已用% 挂载点
/dev/vda1 40G 18G 20G 49% /
tmpfs 977M 512K 977M 1% /dev/shm
这个命令是我用得最多的,一眼就能看出磁盘还剩多少。
df -h 指定目录
# 查看某个目录所在分区的磁盘情况
df -h /var/log
这个用法特别实用,可以快速确认某个目录落在哪个磁盘分区上。
进阶骚操作
-T:查看文件系统类型
# 加上-T能看到每个分区的文件系统类型(ext4、xfs、tmpfs等)
df -hT
# 输出示例
文件系统 类型 容量 已用 可用 已用% 挂载点
/dev/vda1 ext4 40G 18G 20G 49% /
tmpfs tmpfs 977M 512K 977M 1% /dev/shm
这个参数在迁移数据或排查文件系统相关的 bug 时很好用。有一次我发现一个目录写不进去东西,用 df -T 一看,挂载的是 vfat 格式,不支持 4G 以上的单个文件,破案了。
-i:查看 inode 使用情况
# 查看inode信息
df -i
# 输出示例
文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点
/dev/vda1 2621440 2621440 0 100% /
这个太重要了! 磁盘空间还有,但是 inode 满了,你一样写不了新文件。这种情况常发生在:
1. 有程序疯狂创建超小文件
2. 邮件队列里堆了几十万封未发送邮件
3. 文件系统上缓存了大量临时文件
我记得有一次半夜三点被叫起来,说服务器上 MySQL 写不了数据了。df -h 看空间还有 30%,折腾了半小时没找到原因。最后是群里一个同事提醒:"看看 inode。"我一看,确实 100% 了。最后发现是 /var/spool/postfix/maildrop 下面塞了上百万个邮件文件,用 find 删掉就恢复了。
df vs du 结果不一致
这是个经典问题。有时候 df -h 显示已用了 30G,但用 du -sh /* 加来加去只有 20G。差出来的 10G 去哪了?
常见原因:
# 1. 已删除但进程还在占用的文件
# 用lsof查看哪些进程占用了已删除的文件
lsof | grep deleted
# 2. 文件系统预留块(默认5%)
# 可以用tune2fs查看
tune2fs -l /dev/vda1 | grep "Reserved block count"
# 3. 元数据也占空间
# 格式化的时候就占了一定比例
解决办法一般是重启那个进程(释放文件句柄),或者用 lsof 找到是哪个进程还在吃,然后重启它。
--output 自定义输出列
# 只显示想看的信息列
df --output=source,fstype,size,used,avail,pcent,target -h
这个我平时用得不多,但写脚本的时候很好用,输出格式干净,方便解析。
避坑指南
坑1:100% 不代表真的满了
df 显示的已用百分比是四舍五入的。比如 df -h 显示 / 用了 100%,但 df 看块数可能还有几十 KB。
而且 ext4 默认给 root 预留了 5% 的空间(为了系统关键进程能用),普通用户写到 95% 就写不进去了,但 root 还可以写。
# 查看预留比例
tune2fs -l /dev/vda1 | grep "Reserved"
# 生产环境根分区建议别动预留,但大容量数据盘可以调小
# 比如把5%改成1%
tune2fs -m 1 /dev/vdb1
坑2:文件系统已用 + 可用 != 总容量
# Linux df显示的"已用+可用"通常小于总容量
# 因为系统预留块、元数据也会占空间
# 这是正常的,不用慌
坑3:df 和实际使用量对不上
前面说了,如果删了大文件但进程没重启,空间不会释放。这时候:
# 找出还在占用已删除文件的进程
lsof -nP | grep '(deleted)' | head -10
# 然后重启对应服务
systemctl restart nginx
坑4:NFS 挂载点 df 慢
如果挂载了 NFS 远程目录,df 可能会卡住(因为要去远程服务器查询)。这时候可以加 --direct 参数或者先卸载 NFS。
# 跳过NFS挂载点
df -h --exclude-type=nfs
# 或者只查本地
df -h -l
实战场景
场景1:磁盘告警排查三板斧
线上服务器磁盘告警了,我的排查流程:
# 第一步:看整体情况
df -h
# 第二步:检查inode
df -i
# 第三步:定位大目录
du -sh /* 2>/dev/null | sort -rh | head -10
# 第四步:如果有已删除但未释放的空间
lsof -nP | grep '(deleted)' | grep -v "perf|trace"
场景2:清理 Docker 日志占满磁盘
Docker 容器日志经常把磁盘撑爆:
# 先看看哪个分区满了
df -h /var/lib/docker
# 查看Docker日志占用
du -sh /var/lib/docker/containers/*/*-json.log
# 清空日志(注意是清空不是删除,否则要重启Docker)
truncate -s 0 /var/lib/docker/containers/*/*-json.log
场景3:写监控脚本
#!/bin/bash
# 检查磁盘使用率,超过80%就告警
THRESHOLD=80
df -hP | grep -v "tmpfs" | grep "^/dev/" | while read line; do
usage=$(echo $line | awk '{print $5}' | cut -d'%' -f1)
mount=$(echo $line | awk '{print $6}')
if [ "$usage" -gt "$THRESHOLD" ]; then
echo "告警:分区 $mount 使用率已达 ${usage}%"
fi
done
场景4:排查新挂载的磁盘
# 云服务器新挂载了一块数据盘,确认是否已挂载
df -h | grep "/data"
# 没出来?看看磁盘有没有被识别
lsblk
# 如果确认设备存在但没挂载,手动挂载
mount /dev/vdb1 /data
df -h /data
今日作业
请使用 df 命令完成以下任务:
1. 用人类可读的格式查看所有本地文件系统(跳过 tmpfs)的磁盘使用情况
2. 单独查看根目录 / 的 inode 使用率
3. 查看 /var 目录所在的文件系统类型是什么(ext4/xfs/其他)
写出对应的三条命令即可。