标准三步
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rl-root 62G 59G 3.0G 96% /
/dev/sda1 1014M 247M 768M 25% /boot
↑ 根分区 96%,就是它
$ sudo du -sh /* 2>/dev/null | sort -rh | head
32G /var
12G /usr
4G /home
# 找到 /var 最大,再往下钻一层
$ sudo du -sh /var/* 2>/dev/null | sort -rh | head
28G /var/log
↑ 一层层缩小范围,直到定位到具体文件
$ sudo du -sh /var/log/* | sort -rh | head -5
# 清理老日志(Day 05 的 -mtime +7)
$ sudo find /var/log -name "*.log" -mtime +7 -delete
# 清理 journal(Day 13 学的)
$ sudo journalctl --vacuum-time=7d
# 清理 dnf 缓存
$ sudo dnf clean all
df 看分区级别(还剩多少),du 看目录级别(谁占的)。先 df 定位分区,再 du 找元凶——顺序反了会在无关分区上瞎找。
加分答案一:lsof | grep deleted
现象:df 说磁盘满了,但 du 一层层加起来对不上——差好几十 G 找不到。
- 原因
- 有人删了一个大日志文件,但写这个文件的进程还开着它。文件名没了(
du看不到),但磁盘空间没释放(dfstill 算着)。 - 典型场景
- 「日志太大我
rm了,怎么磁盘还是满的?」——因为 nginx / java 进程还占着那个已删除的文件句柄。 - 怎么找
sudo lsof | grep deleted- 怎么解决
- 重启那个进程,句柄释放,空间立刻回来。或者用
> /proc/PID/fd/N清空它。
$ sudo lsof | grep deleted
nginx 3412 nginx 6w REG 253,0 21474836480 /var/log/nginx/access.log (deleted)
↑ 20G 的已删除文件还占着
# 方法一:重启服务(最简单)
$ sudo systemctl restart nginx
# 方法二:不重启,直接清空那个文件句柄
$ sudo truncate -s 0 /proc/3412/fd/6
$ df -h # 空间回来了
清空一个正在被写入的日志,不要用 rm,要用 truncate 或者重定向:
sudo truncate -s 0 /var/log/nginx/access.log
或者 sudo sh -c '> /var/log/nginx/access.log'
这样文件还在、句柄还在、空间立刻释放,服务也不用重启。
加分答案二:inode 耗尽
现象:df -h 显示还有空间,但就是写不进去,报 No space left on device。
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/rl-root 3.9M 3.9M 1.2K 100% /
↑ inode 用光了
- 概念
- 每个文件都要占一个 inode(存元数据的槽位)。格式化时数量就定死了。
- 什么时候会爆
- 海量小文件——session 文件、缓存碎片、邮件队列。空间没用完,但槽位用光了。
- 怎么找
sudo find /var -xdev -type f | cut -d/ -f1-4 | sort | uniq -c | sort -rn | head——按目录统计文件数量而不是大小。
「磁盘满了怎么查」——大部分人答到 df + du 就没了。
你能接着说出「如果 df 和 du 对不上,查 lsof deleted」和「如果空间够但写不进去,查 df -i 看 inode」,面试官立刻知道你真处理过线上磁盘告警。
其他常用
$ lsblk # 磁盘、分区、挂载点的树状图
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 64G 0 disk
├─sda1 8:1 0 1G 0 part /boot
└─sda2 8:2 0 63G 0 part
└─rl-root 253:0 0 62G 0 lvm /
$ df -hT # -T 显示文件系统类型(xfs/ext4)
$ du -sh /var/log # 单个目录总大小
$ du -h --max-depth=1 /var # 只看一层,等价于 du -sh /var/*
du 和 find 加上 -xdev(或 -x)表示不跨越文件系统边界。
否则你在 / 上找大文件,会把挂载在下面的其他分区、网络存储也算进去,结果对不上还浪费时间。
今天的面试点
主线:「df -h 先定位哪个分区 → du -sh /* | sort -rh 逐层往下找大目录 → 找到具体文件后清理,一般是日志。」
加分一:「如果 df 显示满了但 du 加起来对不上,那多半是有进程占着已删除的文件,lsof | grep deleted 能查到,重启那个服务空间就回来了。」
加分二:「还有一种情况是空间够但 inode 用完了,df -i 能看出来,通常是海量小文件导致的。」
「不建议。如果服务还在写它,rm 之后空间不会释放,还得重启服务。」
「我一般用 truncate -s 0 清空——文件还在、句柄还在、空间立刻释放,服务不用重启。长期方案是配 logrotate(第 29 天)。」
今天的练习
df -h和df -i各看一次,理解两者查的是不同的东西lsblk,画出你这台虚拟机的磁盘结构(注意rl-root那个 lvm,后天要用)- 逐层往下钻:
sudo du -sh /* | sort -rh | head→ 挑最大的再钻一层 → 再一层 - 重点实验:造一个 500M 的大文件
sudo dd if=/dev/zero of=/var/log/big.log bs=1M count=500,用df -h看空间变化,再rm掉看空间是否立刻回来 - 再做一次 deleted 实验:
sudo tail -f /var/log/big2.log &挂着 → 另开窗口rm掉它 →df -h看空间没回来 →sudo lsof | grep deleted找到它 →kill掉 tail → 空间回来 sudo lsof | grep deleted | head,看你机器上有没有这种情况
Day 22 给虚拟机加一块新硬盘,走一遍分区 → 格式化 → 挂载 → 写 fstab 的完整流程。
这是最接近真实工作的练习,也是 /etc/fstab 写错会导致系统开不了机的那一天。