磁盘明明还有空间,服务却写不进文件:多半是 inode 用完了
前几天遇到一个很迷惑的故障:一台服务器上的应用突然报错,日志写不进去、文件上传失败,错误信息统一是 No space left on device。可登上去一看,df -h 显示根分区还剩三十多 G,怎么看都不像没空间的样子。最后定位下来,满的不是磁盘容量,而是 inode。
inode 是什么,为什么会先耗尽
文件系统里,每个文件(包括目录、软链接)都要占一个 inode,用来记录大小、权限、数据块位置这些元信息。建文件系统时 inode 的总数就基本固定了,容量再大,inode 用完一样建不了新文件。最容易把它吃光的,恰恰是「数量多、个头小」的文件:磁盘空间还没用多少,inode 已经被几百万个小文件占满了。
三步定位
第一步:确认是不是 inode 的问题。
df -i
看目标分区的 IUse%,如果是 100%,基本就实锤了。这一步只要十秒,能少走很多弯路——我一开始还去查了配额和只读挂载,全是白费功夫。
第二步:找出哪个目录在囤小文件。
du --inodes -d 2 /var 2>/dev/null | sort -n | tail -20
按 inode 占用从大到小排,很快能锁定大户。也可以换成 /usr、/ 逐层往下钻。
第三步:对着清单认元凶。 实际遇到的高频选手有这几类:
- 邮件队列:
/var/spool/postfix/maildrop里积压的未发送邮件,程序报错时疯狂发信,几万封就是几万个 inode; - 会话文件:PHP 的 session 目录、框架的缓存目录,过期文件没人清;
- 应用缓存与临时文件:缩略图、编译缓存、分片上传的残片;
- Docker 场景:容器日志和 overlay 层里的小文件同样占宿主机 inode,别只盯着业务目录。
处理与预防
处理先做减法:清掉过期的 session 和缓存、处理积压邮件、给日志目录补上 logrotate 轮转规则。注意删之前先确认这些文件确实是可再生或已过期的,别把业务数据当垃圾清了;量大的时候用 find 目录 -type f -mtime +7 -delete 分批删,一次性 rm 几百万个文件容易把 IO 打满。
预防比抢修重要,两件事值得做:
- 监控加上 inode 使用率告警,80% 就报警。很多监控模板只盯容量百分比,inode 满的时候容量告警是不会响的,这次就是吃了这个亏。
- 小文件密集的目录单独规划:比如把缓存、会话目录单独挂载一个文件系统,或者格式化时用
mkfs.ext4 -i 8192适当调高 inode 密度(bytes-per-inode 调小),让inode 数量跟得上业务形态。
小结
No space left on device 不等于磁盘满。下次再碰到空间类报错,排查顺序可以是:df -h 看容量 → df -i 看 inode → du --inodes 找大户 → 对照元凶清单清理并补监控。这个顺序走一遍,十分钟内基本能定位,比对着「明明还有空间」的假象反复重启服务靠谱得多。
- 点赞
- 收藏
- 关注作者
评论(0)