Skip to content

Linux 磁盘占满排查

磁盘占满是运维里最常见、也最容易被低估的问题之一。它的麻烦不在于判断难,而在于它一旦发生,影响通常是连锁的:日志写不进去、服务无法启动、容器无法拉镜像、数据库开始报错,最后整个系统会像被一点点掐住呼吸一样变慢。

这篇记录模拟一次比较典型的排查过程:机器在白天工作正常,到了下午突然开始报错,监控里最先出现的是磁盘使用率持续攀升,随后系统服务开始异常。

现场症状

最早看到的信号通常比较简单:

  • 日志轮转失败
  • 新文件写入报错
  • 某些服务突然退出
  • 监控面板上磁盘使用率接近 100%

在这种情况下,第一反应不要急着清理,而是先确认到底是哪一个挂载点满了。很多时候并不是整台机器都满,而只是某个分区、某个数据盘或者某个临时目录被写爆了。

bash
df -h
df -ih
mount

如果 df -h 看起来还没满,但系统已经开始报磁盘相关错误,那么还要顺手看 inode 是否耗尽。inode 满了以后,表现和磁盘满很像,但处理思路完全不同。

先找大户

确认是哪个挂载点之后,就要定位大目录。最直接的方式通常是从根目录往下扫:

bash
du -sh /* 2>/dev/null
du -sh /var/* 2>/dev/null
du -sh /var/log/* 2>/dev/null

如果目录特别多,也可以用更细一点的方式:

bash
find /var -xdev -type f -size +100M -printf '%s %p\n' | sort -nr | head

这一步通常会把嫌疑范围缩小到几个地方:

  • /var/log
  • /var/lib/docker
  • /var/lib/containerd
  • 某些应用的数据目录
  • 临时文件和缓存目录

实际处理时,最怕的是“看起来都不大,但磁盘就是一直在涨”。这通常意味着日志仍在疯狂写入,或者有进程在不断生成临时文件。

日志清理

如果问题主要出在日志,最稳妥的做法不是直接 rm 一堆文件,而是先确认日志服务和轮转机制是否正常。

bash
journalctl --disk-usage
journalctl --vacuum-time=7d

对于 systemd-journald,如果日志已经堆积很多,适度清理是合理的。但清理之前最好确认最近的关键错误已经看过,不然回头排障时会少掉很重要的上下文。

如果是传统文件日志,可以配合看:

bash
logrotate -d /etc/logrotate.conf
ls -lh /var/log

这里有一个很实用的经验:删文件不等于释放空间。某些进程可能已经打开了被删除的文件句柄,这时候 du 看不出来,df 还是满。

bash
lsof | grep deleted

如果看到某个进程一直占着已经删除的超大文件,最有效的方式往往是让对应服务重载或重启,而不是继续删更多文件。

容器磁盘

如果机器上跑了 Docker,还要特别看容器层:

bash
docker system df
docker ps -a
docker images

镜像缓存、停止的容器、构建遗留层都会慢慢吞掉磁盘。常见的清理方向有:

  • 清理无用镜像
  • 清理停止容器
  • 清理构建缓存
  • 检查日志驱动是否无限增长
bash
docker system prune -af
docker builder prune -af

这类命令需要谨慎使用,尤其在共享环境里。我的习惯是先确认哪些镜像和容器是可以清理的,再下手,不要把“省空间”做成“删错东西”。

根因判断

处理到这里,通常可以开始回看根因。常见原因大概有几类:

1. 业务日志量突然激增

比如某个任务进入了异常循环,日志一直刷屏,最终把磁盘写满。

2. 轮转策略不合理

日志轮转周期太长、保留文件太多、压缩策略不合理,都会让磁盘慢慢被吃掉。

3. 临时文件没有被及时清理

某些程序会在 /tmp 或工作目录里留下大量中间文件,长时间运行后就会形成积累。

4. 容器层膨胀

镜像、日志和构建缓存会在不知不觉中变大,尤其是开发机和测试节点。

验证

清理完成后,不要只看磁盘数字下降,还要确认服务已经恢复正常:

bash
df -h
systemctl --failed
journalctl -p err -xb

如果应用层已经恢复,最好再做一次写入验证,确认原本报错的目录可以正常写入。

bash
touch /var/tmp/disk-check
rm -f /var/tmp/disk-check

复盘

磁盘占满这类问题最值得记录的,不是“删了多少 G”,而是以后怎么尽量不再发生。比较实用的复盘项包括:

  • 哪个目录最容易涨
  • 是否需要单独做磁盘告警
  • 日志轮转是不是太宽松
  • 容器日志是否应该限制大小
  • 是否要把临时文件改到独立挂载点

很多运维故障都不是因为系统设计得很差,而是因为本来应该被提前约束的增长,没有被持续盯住。把这件事记录下来,后面再碰到类似情况就会快很多。

Focused notes for DevOps, Linux and Kubernetes.