磁盘还有空间却写不进去:inode 耗尽与已删除大文件的排查顺序

举报
yd_217417492 发表于 2026/11/05 09:11:00 2026/11/05
【摘要】 df 显示还有几十 GB,写入却报 No space left on device。这类问题通常不是 block 用尽,而是 inode 耗尽,或者文件已被删除但句柄还没释放。本文给出三步排查顺序和对应的处理方式。

先分清两种「没空间」

看到 No space left on device,第一反应通常是磁盘满了。但 Linux 上文件系统有两类资源:数据块(block)和索引节点(inode)。任何一类用尽,写入都会失败,而报错信息完全一样。所以第一步不是删文件,而是分别确认这两类资源的状态:

df -h /var
# Filesystem      Size  Used Avail Use% Mounted on
# /dev/vda1        40G   18G   22G  45% /

df -i /var
# Filesystem      Inodes  IUsed   IFree IUse% Mounted on
# /dev/vda1      2621440 2621440      0  100% /

上面这个例子很典型:block 只用了 45%,但 inode 已经 100%。此时无论怎么清理大文件都没用,因为缺的是「文件条目的名额」,不是存储空间。

一、inode 耗尽:先找小文件扎堆的目录

inode 数量在格式化时就固定了,每个文件、目录、符号链接都至少占一个。耗尽 inode 的从来不是大文件,而是数量巨大的小文件,常见来源有:

  • 应用把每个请求写成一个小日志或临时文件,且从不清理;
  • PHP/Python 的 session 文件、缓存碎片堆在同一个目录;
  • 邮件队列、监控采集数据按秒落盘;
  • 容器层里反复构建留下的中间文件。

按目录统计文件数量,从根往下逐层缩小范围:

for d in /var/*; do
  printf '%8s  %s\n' "$(find "$d" -xdev -type f 2>/dev/null | wc -l)" "$d"
done | sort -rn | head -20

找到数量异常的目录后,先确认这些文件是否还在被使用,再按修改时间清理,例如只删除 7 天前的缓存:

find /var/cache/app -xdev -type f -mtime +7 -delete

如果单个目录里就有几百万个文件,rm 会非常慢,而且可能再次把 inode 占满。更稳妥的做法是先停掉写入方,用 rsync -a --delete 同步一个空目录过去,或者直接重建目录。清理完成后用 df -i 确认 IUse% 是否降下来。

二、文件已删除,但空间没回来

另一种情况是 df 显示快满了,du 却怎么也对不上。原因通常是某个进程还持有已删除文件的句柄:文件在目录里已经看不见,但数据块要等进程关闭句柄才会释放。用 lsof 找 deleted 标记:

lsof +L1 2>/dev/null | sort -k7 -rn | head
# COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK   NODE NAME
# python3 18422 root    3w   REG  253,1 12G     0 131074 /var/log/app.log (deleted)

处理方式取决于进程:能重载就重载(例如 systemctl reload 或 kill -HUP),不能重载就只能重启。日志类文件还有一个更温和的办法:清空而不是删除,让写入方继续用同一个 inode:

truncate -s 0 /var/log/app.log

这样既释放了空间,也不会因为 inode 被替换导致进程继续往「看不见的文件」里写。

三、确认是不是文件系统或配额问题

如果 block 和 inode 都不是 100%,还要看两个地方。一是挂载点是否写满,比如 /var/lib/docker 单独挂了一块小盘,根分区正常但容器写不进去;二是是否启用了磁盘配额:

findmnt -T /var/lib/docker
repquota -a 2>/dev/null | head

容器环境还要注意 overlay 层:镜像层是只读的,写入都落在可写层,docker system df 看到的占用和宿主机 df 往往不是一回事。

四、把监控补上,别等报错才发现

inode 使用率应该和磁盘使用率一起监控。很多监控模板只采集 df -h,漏掉了 df -i,结果就是空间看着很健康,服务却突然写不进日志。最简单的做法是在现有巡检脚本里加一行判断:

df -i --output=pcent /var | tail -1 | tr -dc '0-9'

超过 80% 就告警。另外给临时目录和缓存目录设置定期清理,日志统一走 logrotate,能避免绝大多数 inode 耗尽问题。

小结

遇到「还有空间却写不进去」,按这个顺序走:先 df -h 和 df -i 分清是 block 还是 inode;inode 满就找小文件扎堆的目录;空间对不上就用 lsof +L1 找已删除但仍被占用的文件。真正要长期解决的,还是把 inode 使用率纳入监控,并给缓存和日志设定明确的清理策略。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。