适用:所有 Linux 耗时:约 25 分钟 前置:E3(会看日志)

磁盘满是最常见的故障,也是最容易搞砸的——很多人为了腾空间,删错了东西,把系统搞坏了。

这一篇只讲两件事:怎么找到谁在吃空间,怎么安全地清。


一、先理解 Linux 的"盘"是怎么组织的

没有 C 盘 D 盘,只有一棵树

Windows:C:\ D:\ 各是一棵树 Linux:只有一棵树,从 / 开始。所有磁盘都"挂"在这棵树的某个目录上。

/                    ← 根,"整棵树"
├── home/            ← 用户文件(最占地方,也最能清)
├── var/             ← 日志、数据库、网站(第二占地方)
├── usr/             ← 程序本体(别手删)
├── etc/             ← 配置(别手删)
├── tmp/             ← 临时文件(可以清)
├── boot/            ← 内核和引导(**动了开不了机**)
└── mnt/  media/     ← 外接盘、U 盘挂在这

关键概念:

  • 分区(partition)= 硬盘上的一块
  • 挂载(mount)= 把某个分区"接"到树上某个目录
  • 挂载点(mount point)= 那个目录
# 看谁挂在哪
findmnt
# 或
mount | column -t

为什么"加硬盘"不等于"空间变大"

新手常问:“我加了一块 1T 硬盘,为什么 /home 还是满的?”

因为硬盘还没挂到 /home 上。 装了硬盘 ≠ 用了硬盘,必须挂载。


二、df:全局视角,谁满了

df -h

输出:

文件系统        容量  已用  可用 已用% 挂载点
/dev/vda1        49G   35G   13G   74% /
/dev/vdb1       100G   20G   75G   21% /data
tmpfs           1.8G  1.2M  1.8G    1% /run

只看四列:容量 已用% 挂载点 文件系统

关键判断:

  • / 到 85% 以上就该处理 —— 到 100% 系统会出各种怪问题(连图形界面都可能起不来)
  • tmpfs 是内存盘,不用管
  • 加到 90% 以上,日志可能写不进去,服务会开始报错

只关心真实磁盘:

df -h -x tmpfs -x devtmpfs

三、du:找到具体是谁在吃

df 告诉你"哪个盘满了",du 告诉你"哪个目录占的"。

从根开始逐层下钻

sudo du -sh /* 2>/dev/null | sort -h | tail -10

sort -h 是按人类可读的大小排序(自动识别 K/M/G),这是关键——用普通 sort 会按字符串排,9G 会排在 10G 前面。

然后进最大那个继续:

sudo du -sh /var/* 2>/dev/null | sort -h | tail -10
sudo du -sh /var/log/* 2>/dev/null | sort -h | tail -10

三步之内,一定找到元凶。

一次看到底(不用逐层下钻)

sudo du -h --max-depth=2 / 2>/dev/null | sort -h | tail -20

--max-depth 控制深度。2 层一般够,3 层太慢。

找大文件(不是大目录)

sudo find / -type f -size +500M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}'

列出所有大于 500M 的文件。 有时候是一个巨大的日志文件或镜像文件。


四、Linux 最坑的一个现象:df 满了,du 加起来却很少

这是新手最容易卡死的地方。

现象

df -h
# /  100% 已用

sudo du -sh /*
# 加起来才 20G,但盘有 49G

差了 30G,找不到。

原因

有个文件被删了,但还有进程开着它。

Linux 的规则:文件被 rm 时,如果还有进程持有它的句柄,文件不会真正释放——空间继续占着,但 du 看不到(因为目录项已经没了)。只有进程关闭句柄,空间才真正释放。

怎么找

sudo lsof +L1

或者:

sudo lsof | grep deleted

输出里 SIZE/OFF 那列就是占的空间。

怎么修

重启那个进程(不是删文件——文件已经删了):

sudo systemctl restart 那个服务

或者找到 PID 直接停:

kill -15 PID

空间立刻释放。

典型场景:nginx 的 access.log 被 rm 了,但 nginx 还在往里写 → 磁盘满但找不到文件。 正确做法:日志不要 rm,要清空:> /var/log/nginx/access.log(这个操作不改变 inode,进程句柄仍然有效)。


五、安全清理:按这个顺序

从最安全的开始,一步步往下。任何时候停下来都不影响系统。

第 1 级:完全安全,随时可清

# apt 缓存(Debian 系)
sudo apt clean

# dnf 缓存(RPM 系)
sudo dnf clean all

# 用户缓存
rm -rf ~/.cache/*

# 缩日志到 500M
sudo journalctl --vacuum-size=500M

# 清 /tmp 里超过 7 天的
sudo find /tmp -type f -atime +7 -delete

这五条清完,一般能腾出几 G,且零风险。

第 2 级:安全,但要先看

# 旧内核(占几百 M 到几 G)
sudo apt autoremove --purge

# 看有多少旧内核
dpkg --list | grep linux-image

# 你自己下载的东西
du -sh ~/下载/* | sort -h | tail -10
du -sh ~/.local/share/Trash/*    # 回收站

第 3 级:需要判断

# Docker(如果装了)
docker system df          # 先看占多少
docker system prune -a    # 清掉没用的镜像和容器

⚠️ docker system prune -a 会删掉所有没在运行的容器和镜像。有在用的会保留,但会删掉你 pull 过但暂时没用的镜像——下次用要重新下载。

⚠️ 绝对不要动的

目录为什么
/boot删了开不了机
/usr系统程序本体
/etc配置
/lib /lib64系统库,删了什么都跑不起来
/var/lib数据库、包管理器状态(乱删会导致系统无法更新)

这些地方出了问题,正确做法是重装或从备份恢复,不是手删。


六、挂载:接一块新硬盘

临时挂载(重启失效)

# 1. 看系统认到新盘没
lsblk

# 输出里多出一个 sdb(没有挂载点)
# sdb
# └─sdb1

# 2. 建挂载点
sudo mkdir -p /data

# 3. 挂上去
sudo mount /dev/sdb1 /data

# 4. 验证
df -h | grep data

永久挂载(写进 /etc/fstab)

必须先拿到分区 UUID(比 /dev/sdb1 稳定,因为设备名可能变):

sudo blkid /dev/sdb1
# /dev/sdb1: UUID="a1b2c3d4-..." TYPE="ext4"

编辑 fstab:

sudo cp /etc/fstab /etc/fstab.bak-$(date +%Y%m%d)   # ⚠️ 先备份!
sudo nano /etc/fstab

加一行:

UUID=a1b2c3d4-...  /data  ext4  defaults,nofail  0  2

关键参数 nofail:如果这块盘坏了或没插,开机不会卡住。 不加这个,盘一坏系统就起不来。

测试(不要直接重启!):

sudo mount -a

没报错 = 配置正确。报错就赶紧改回来,否则下次开机会进紧急模式。

⚠️ fstab 写错会导致系统开不了机。 这是新手最容易造成"系统损坏"的操作。 改了 fstab,一定要先 sudo mount -a 验证,再重启。


七、动手:四个练习

练习 1:看清自己的磁盘布局

df -h -x tmpfs -x devtmpfs
sudo lsblk
findmnt | head -20

把「哪个分区挂在哪」搞清楚。

练习 2:找出前 3 个最占地方的目录

sudo du -sh /* 2>/dev/null | sort -h | tail -3

只看,不动。

练习 3:安全清理一次

# 先记录清理前
df -h /

sudo apt clean
sudo journalctl --vacuum-size=200M
rm -rf ~/.cache/*

# 再看清理后
df -h /

对比一下腾出了多少。

练习 4:验证 fstab 配置(不改,只验证)

sudo mount -a
echo "退出码: $?"

退出码 0 = 当前 fstab 配置正确。 养成改完就跑一下的习惯。


八、验证:你过关了吗

  • 会用 df -h 看哪个分区满了
  • 会用 du -sh * | sort -h 逐层下钻
  • 知道 df 和 du 对不上时用 lsof +L1
  • 知道日志要用 > 清空而不是 rm
  • 知道哪些目录绝对不能删
  • 会挂载新磁盘,会用 UUID 写 fstab,知道 nofail 的作用
  • 改完 fstab 会先 mount -a 验证

九、不行怎么办

Q1:df 和 du 都算不出空间去哪了 可能是被删除但被打开的文件(见第四节),也可能是inode 用完了:

df -i          # 看 inode 使用率

inode 满了也是"磁盘满"的一种——表现为无法创建新文件,但 df -h 显示还有空间。 原因:某个目录里有几百万个小文件(常见于日志目录、缓存目录、邮件队列)。 修法:找出小文件最多的目录,批量清理:

sudo find /var -type f | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -10

Q2:mount 报 unknown filesystem type 'ntfs'

sudo apt install ntfs-3g      # Debian 系
sudo dnf install ntfs-3g      # RPM 系

Q3:挂载后目录里是空的 / 原来的文件不见了 挂载会"遮住"挂载点原来的内容。 卸载后就回来了:

sudo umount /data

所以挂载点应该用空目录。

Q4:umount 报 target is busy 有进程在用这个目录:

sudo lsof +D /data       # 看谁在用(大目录会慢)
sudo fuser -mv /data     # 更快

先退出来,或者杀掉进程,再卸载。

Q5:权限问题,普通用户挂不了盘 挂载需要 root。日常用图形界面会自动处理;命令行一律 sudo。

Q6:扩容了云盘,但 df 还是老大小 扩容分两步:① 云控制台扩大磁盘 ② 系统内扩展文件系统。

# 先看分区
sudo lsblk

# ext4 扩展(分区已经是新的,只需扩文件系统)
sudo resize2fs /dev/vda1

# xfs
sudo xfs_growfs /

如果分区本身也没扩,还需要 growpart:

sudo growpart /dev/vda 1
sudo resize2fs /dev/vda1

十、一句话总结

df 看哪个盘满,du 找谁占的,sort -h 排序,逐步下钻。

df 满但 du 找不到 → lsof +L1(文件被删但进程还开着)。

清理从 apt clean 开始,/boot 和 /usr 永远别碰。


← 上一篇 E4|网络排查 下一篇 → E6|Shell 脚本:把重复操作变成一条命令