磁盘没满却写不进去:inode 用尽的排查
发布时间:2026-04-05 20:17       
更新时间:2026-04-06 01:42
报错写着 No space left on device,df -h 却显示还有大把空间,这种情况八成卡在 inode 上,先跑 df -i 验证。这类报错的迷惑性在于提示没错:站在文件系统的角度,账本满了就是写不进。
inode 是什么?
文件系统给每个文件分配一个 inode(索引节点),存放元数据,数量在格式化时就定死了。磁盘空间和 inode 是两本账:一个只有 1 字节的文件,也实打实占一个 inode。df -i 里 IUse% 到 100%,就是账本满了,哪怕空间没写满,新文件也进不来。
海量小文件藏在哪?
逐层数每个目录下的文件数量:
for i in /*; do echo "$i $(find $i -xdev 2>/dev/null | wc -l)"; done
数字大的那层往里钻,重复执行就能定位。常见嫌疑地:session 文件目录、编译缓存、缩略图缓存,还有头号惯犯 clientmqueue——cron 任务输出无人接收、系统又没配邮件服务,邮件就在 /var/spool 里堆成几十万个小文件。
怎么清?
确认目录没有业务价值后批量删:find /var/spool/clientmqueue -type f -print 先看清单,核对无误把 -print 换成 -delete。文件量到百万级时,一条命令删到底会拖慢系统,可以分批:find 目录 -type f | xargs -n 1000 rm -f。删完 df -i 看使用率回落,IUse% 回到个位数才算清干净。删除动手前把各目录的文件数记一份快照,事后写故障报告,数字都是现成的。顺带排除一种假象:文件已删但进程还握着句柄,df 与 du 对不上,lsof | grep deleted 找到进程,重启它即释放。
怎么防?
给会产生海量小文件的目录配定期清理,find 目录 -type f -mtime +7 -delete 放进 cron;系统临时目录的清理可以交给 systemd-tmpfiles,规则写在 /etc/tmpfiles.d/,比手写脚本规范。清理任务错峰放在业务低谷,避免和备份撞车。ext4 默认大约每 16KB 空间配一个 inode,正常场景够用;专门存海量小文件的分区,建小一些或用 mkfs.ext4 -i 调整密度,这事要在设计阶段定,事后只有重建文件系统一条路。复盘时把 inode 密度写进方案评审清单,与容量、IOPS 一起过。