4.2 磁盘满了怎么办:先找罪魁,再动手删

先给一个判断

磁盘满的排查就一句话:先定位是谁吃的,再决定删什么。 df -h 只能告诉你“满了”,du 才能告诉你“谁吃的”。很多人一看磁盘红了就急着清缓存、删日志,结果删了半天空间没释放多少,因为真正的大头是某个几十 G 的备份包或者容器日志。删错文件的空间是回不来的,删之前先看清楚。

第一步:确认是不是真的满了

# 看各分区的使用率(重点看 Use% 和挂载点)
df -h

# 看 inode 占用(小文件太多会先耗尽 inode)
df -i

一个经典误区:df 显示 100% 满,但你 du 加起来不到一半。这种情况通常是有文件被删了但进程还拿着句柄——空间没真正释放。验证方法:

# 列出所有"已删除但仍被占用"的文件
lsof +L1 2>/dev/null | awk 'NR==1 || $7+0 > 1048576' | head -20

看到这种文件,重启占用它的进程(或整个应用容器),空间立刻就回来了。典型例子:某个网站日志被直接 rm 删掉,但 OpenResty 还在往里写。

第二步:找到大文件

# 根目录下各目录占用(从大到小排,只看前十)
du -sh /* 2>/dev/null | sort -rh | head -10

# 顺藤摸瓜,继续进最大的那个目录
du -sh /var/* 2>/dev/null | sort -rh | head -10

# 直接揪出所有大于 500M 的文件
find / -xdev -type f -size +500M 2>/dev/null | head -20

du 一定要加 -x 或只在同一个分区内查,不然把别的挂载点(比如云数据盘)也算进来,数字大得吓人还没用。

1Panel 环境的三个重灾区

目录 装的什么 能不能清
/opt/1panel 面板数据、应用、备份、日志 用面板的缓存清理,别手 rm
/var/lib/docker 镜像、容器日志、存储卷 用 docker 命令清,见下
网站日志目录 OpenResty 的访问/错误日志 用日志切割,见 4.4 节

Docker 占用的查看和清理:

# 看各类 Docker 占用(镜像、容器、日志、卷分开显示)
docker system df -v

# 清掉停止的容器、无用镜像、构建缓存(占用空间的大户)
docker system prune -f

# 更彻底:连无用存储卷一起清(确认没有要用的卷再执行)
docker system prune -a -f --volumes

一句提醒:docker system prune -a 会删掉所有未被运行中容器使用的镜像。力气很大,删之前确认没有“停着备用”的应用。稳妥的做法是先 docker images 看一眼,心里有数再执行。

inode 占用:磁盘没满但写不进文件

症状很有欺骗性:df -h 才用 30%,但应用报“No space left on device”,数据库写不进数据,网站传不了图。这时候去看 df -i,多半是 100%。

inode 是文件的户口本——每个文件占一个,不管文件多小。一个目录里塞几百万个小文件(典型是邮件队列、缓存碎片、Redis 持久化的小 key 文件), inode 先用光,磁盘空间还剩一大堆。

# 找出哪个目录文件数最多(统计较慢,建议先在可疑根目录跑)
for d in /*; do
  [ -d "$d" ] && echo "$(find $d -xdev -type f 2>/dev/null | wc -l) $d"
done | sort -rn | head -10

处理思路:找到那个海量小文件目录,确认它是什么(多半是某应用的缓存或队列),用应用自己的清理命令清,或者直接整目录删——删几百万个小文件用 rm -rf 会很慢,可以用 rsync --delete 空目录覆盖,快得多。

安全清空间的标准顺序

按照“从安全到危险”的顺序删,每删一步看一下 df -h:

  1. 面板缓存清理:工具箱 → 缓存清理,勾选系统垃圾、容器垃圾、临时文件、系统日志——这是最安全的一步,面板自己知道什么能删;
  2. Docker 无用镜像:docker system prune -f,清掉停止容器和无用镜像;
  3. 旧备份文件:备份列表里超过保留份数的老备份,确认不需要后删;
  4. 容器日志:见 4.4 节的日志切割,别上来就删;
  5. 应用数据——这一步开始就要格外谨慎了,删之前先备份。

一条红线:/opt/1panel 下的数据库数据目录、应用数据卷,不要用命令行直接删。要删走面板的备份/应用管理入口,面板知道它们的依赖关系。手 rm 容易留下半拉子状态,应用起不来你都不知道少了什么。

面板里的磁盘工具

1Panel 在 系统 → 磁盘管理 里能看各磁盘的容量、使用率和挂载点;未分区的云数据盘可以在页面里直接分区、格式化、挂载,支持 ext4 和 xfs。如果新买了一块数据盘,比起往系统盘里硬塞,挂一块新盘、把备份目录挪过去,是更彻底的解决办法。

分区有风险:官方文档明确说分区和创建文件系统会清除目标磁盘上的原有数据,1Panel 不会替你判断磁盘里有没有有效数据,操作前一定核对设备名。

一个完整的复现与修复

现象:面板提示磁盘空间不足,网站传图片失败,数据库也开始报错。

排查过程:

  1. df -h —— 根分区 97%,确实快满了;
  2. du -sh /* | sort -rh | head —— /var 占了 60G,最大头;
  3. du -sh /var/* | sort -rh | head —— /var/lib/docker 占 40G;
  4. docker system df -v —— 容器日志占了 18G,其中一个应用容器单日志就 12G(这个应用跑了大半年,从没配过日志大小限制)。

修复:

  1. 先用面板 缓存清理 清掉系统垃圾和停止容器,腾出 3G 应急(先让数据库能写,止血第一);
  2. 然后按 4.4 节的方法给所有容器加上日志大小限制,截掉历史日志;
  3. 最后给备份任务设上保留份数,防止备份无限堆积。

复盘要点:这个案例里真正的问题不是“磁盘小”,而是没有任何东西在限制增长——日志无限制地写、备份无限制地留。清空间是治标,给每个会增长的东西设上限,才是治本。

预防:让磁盘别再悄悄满

手段 怎么做 一次配置长期生效
备份保留份数 计划任务里设保留份数 自动滚动删除旧备份
网站日志切割 计划任务 → 切割网站日志 配合保留份数自动清
容器日志限制 修改 Docker daemon 配置 见 4.4 节
监控告警 面板监控关注磁盘曲线 临满前能看出来

一个习惯:df -h 这条命令成本为零,每次登上服务器顺手敲一下。磁盘从 70% 涨到 95% 通常要好几周,它从来不是突然满的,只是你没看。

本节要点

  • 先 df -h / df -i,确认是空间满还是 inode 满,两者处理方式完全不同;
  • 删文件后空间没释放,用 lsof +L1 查“被删但仍被占用”的文件,重启进程即可;
  • 找大文件用 du -sh | sort -rh 逐层深入,Docker 用 docker system df;
  • 清空间从面板缓存清理开始,应用数据目录不要手 rm;
  • 治本之道是给备份、日志设置保留份数和大小限制。

更多磁盘管理能力见 1Panel 官方文档:磁盘管理,以官方文档为准。

下一节:磁盘清完了,如果 free -h 里available 内存也见底——4.3 节说内存和慢查询怎么治。