磁盘没满却写不进去:No space left on device 其实是 inode 耗尽

举报
shijiu_dev 发表于 2026/11/05 09:13:56 2026/11/05
【摘要】 df -h 显示磁盘还有一半空间,写文件却报 No space left on device。本文从 inode 数量、目录结构、排查命令到预防措施,完整说明这类隐性磁盘写满问题的定位思路。

现象:磁盘没满,程序却写不进文件

有个批量导入服务在跑了几小时后开始报错,日志里反复出现:

OSError: [Errno 28] No space left on device

第一反应是磁盘满了,但运维查 df -h 发现使用率才 50% 左右,inode 使用率也显示 50%。既然两个指标都有一半空间,问题出在哪?

这里有个容易被忽略的点:df -h 显示的是数据块的使用情况,而 df -i 显示的是 inode 的使用情况。两者是独立的两套配额。inode 用满了,即使数据块还有大量空闲,新文件照样创建不了,因为系统找不到空闲的目录项来记录这个文件。

先分清是哪一种"满"

df 的输出里有两行关键信息:

Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb1       100G   50G   50G  50% /
  • Use% 是按数据块算的,超过 90% 需要清理空间。
  • Use% 出现在 IUse% 列且接近 100%,说明是 inode 耗尽。

一条命令同时看两者:

df -h /var /tmp && df -i /var /tmp

如果 df -i 的 IUse% 已经 100%,那磁盘"看起来还有空间"就是错觉。

定位是谁吃掉了 inode

inode 数量和目录下的文件数直接相关,所以找问题要沿着目录树往下走:

# 找出 inode 占用最多的前十个目录
sudo find / -xdev -type d -print0 2>/dev/null | \
  sudo xargs -0 -I{} sh -c 'echo "$(ls -A "{}" | wc -l) {}"' | \
  sort -rn | head -10

重点排查这几个常见位置:

  • 应用日志目录:日志切分产生了成千上万个历史文件,每个文件都占一个 inode。
  • 临时目录:CI 构建产物、临时解压目录、缓存分片。
  • 数据库 binlog:MySQL 的 binlog 按大小滚动正常,但按时间滚动且保留期很长时,文件数量会失控。
  • session / 队列目录:以每个会话一个文件的方式存储数据。

找到嫌疑目录后,看具体是什么在增长:

ls -lS /var/log/app | head -20
find /var/log/app -type f -mtime -1 | wc -l

第二条命令特别有用——统计最近一天新增的文件数,如果远大于预期,说明还有程序在持续制造小文件。

为什么小文件比大文件更容易撑爆 inode

一个 1MB 的文件和一个 1KB 的文件,占用的数据块几乎一样多,但各占一个 inode。inode 的数量级是十万到百万,如果业务按"一个订单一个文件""一次任务一个临时文件"的方式写入,一天就能生成几十万甚至上百万个 inode。

另一个容易被忽略的场景:目录本身也会消耗内存和 inode,但它是独立于文件计数的。大量空目录同样会拖慢文件系统的元数据操作。

修复与清理

确认是可清理文件后,先确认没有进程正在占用:

sudo lsof +L1 | head -20

+L1 表示已删除但仍被进程持有的文件。这类文件不占 inode,但会占着磁盘空间不放,是另一个常见的"空间没释放"来源。

清理时优先用 find 按时间筛,而不是 rm -rf 整个目录:

# 删除 30 天前的日志,保留目录结构
sudo find /var/log/app -type f -name "*.log" -mtime +30 -delete

对正在写入的目录,更稳妥的做法是先轮转、再删除:把当前日志改名,进程会重新创建新文件,然后删除改名的旧文件。这样不会出现应用因为文件句柄丢失而报错。

如果发现是某个程序的写法有问题,根因要修在程序侧。比如把"每个订单一个文件"改成按日期分目录、单文件追加写入,或者直接落到数据库 / 对象存储上。

预防:把 inode 纳入监控

inode 耗尽往往来得比磁盘空间更突然,因为它是一个离散的上限值,等到监控报警时往往已经很满了。建议把 df -i 的使用率和 find 统计的日新增文件数一起纳入告警,并且在配置日志切分时明确设定保留文件数量上限,而不只设定单文件大小或保留天数——很多日志轮转策略只控制体积,不控制数量。

排查这类问题的通用思路是:先分清是数据块还是 inode,再用 find 沿目录树定位,最后从程序侧根治。数据块满了和 inode 满了,症状相似但抓手完全不同,把它们当成两个独立指标来盯,才不至于在"磁盘明明没满"的困惑里绕圈子。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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