Linux 磁盘写满却找不到大文件:一套可复用的排查流程部署任务突然失败,控制台抛出 No space left on devi
部署任务突然失败,控制台抛出 No space left on device。df -h 一看,根分区确实 100%,但用 du -sh 从根目录逐级查下去,把所有目录加起来也远小于磁盘总量。这种情况在运维中非常常见,本文整理一套可复用的排查顺序。
一、先分清是块空间还是 inode
df -h 看的是块空间,df -i 看的是 inode 数量,两者耗尽时报错信息完全一样。
日志被切成大量碎片、容器镜像层很多、邮件队列堆积这类场景,往往是 inode 先满:df -i 显示 IUse% 已经是 100%,而 df -h 还剩不少空间。第一步就必须确认是哪一种,否则后面会白查。
二、du 和 df 对不上,最常见的原因是文件被删了但还被占着
Linux 下执行 rm 删除文件,只有当所有打开它的进程都关闭文件描述符之后,磁盘空间才会真正释放。如果运维删掉了一个正在被写入的日志文件,写入进程还在运行,那么 df 依然显示占满,du 却统计不到这个文件 —— 因为它已经从目录树里消失了。
排查命令:lsof +L1,或者 lsof | grep deleted。
如果看到形如 /var/log/app.log (deleted) 且 SIZE 列很大的条目,那就是元凶。
处理方式不要急着重启服务,更安全的是直接截断:: > /proc/PID/fd/N,其中 PID 和 N 从 lsof 的输出里取。这样能保留进程状态,生产环境优先用这种办法。
三、确认空间真的被目录占用时的逐级定位
du -h --max-depth=1 / 2>/dev/null | sort -hr | head -20
从根目录开始,每层取占用最大的前 20 个目录,然后进入可疑目录重复这一步。加 2>/dev/null 是为了忽略权限不足的报错,避免噪声淹没结果。
如果机器上装了 ncdu,用它更直观,交互式界面可以直接下钻。
这里有个容易踩的坑:du 默认会向下遍历到其他挂载的文件系统。宿主机上挂了 NFS 或者数据盘时,结果会把挂载点里的内容也算进去,导致误判。加上 -x 参数可以限制在当前文件系统内:du -x -h --max-depth=1 /。
四、容器环境还要多看一层
如果是 Docker 或 Kubernetes 的宿主机,磁盘常常被下面这些东西吃光:
/var/lib/docker/overlay2 —— 镜像层和容器可写层;
已经停止但没有删除的容器,用 docker ps -a 查;
悬空镜像,用 docker image prune 清理;
容器标准输出日志,路径是 /var/lib/docker/containers/容器ID/容器ID-json.log。日志驱动没有配置 max-size 时,这个文件会无限增长,是最隐蔽的一类。
一次性清理可以用 docker system prune -a --volumes,但要注意它会删掉未使用的卷,生产环境务必先确认。
五、把预防做在前面
logrotate 配置完整,容器日志显式配置 max-size 和 max-file;监控不要只盯 df -h,把 df -i 一起加上;关键分区水位告警设在 80% 预警,而不是等到 95% 才报,留出处理时间。
小结
遇到磁盘写满,按这四个顺序走基本都能在几分钟内定位:先分清块空间还是 inode,再查已删除但未释放的文件,然后用 du -x 逐级定位大目录,最后别忘了容器和日志这两层。
- 点赞
- 收藏
- 关注作者
评论(0)