磁盘有空间却写不进文件,先用 df -i 查 inode
磁盘有空间却写不进文件,先用 df -i 查 inode
什么情况下会撞上它
df -h 显示还剩几十 GB,但新建文件、写日志、解压、git clone 全部失败,报错:
No space left on device
df -h 统计的是块,文件系统还要为每个文件分配一个 inode(记录元数据、指向数据块的结构)。块够用、inode 不够,一样写不进去。
典型场景是文件数量极多而单个文件很小:邮件队列、session 目录、缓存目录、大量小图片或小日志、容器层里的小文件。几个巨大的视频文件几乎不会耗尽 inode。
为什么这么判断有效
两个命令看的是同一块磁盘的两个独立资源:
df -h # 块用量,还剩多少空间
df -i # inode 用量,还能建多少个文件
df -h 有余量而 df -i 的 IUse% 接近或等于 100%,问题就定位了。inode 数量在 mkfs 时就固定,之后不能扩容,只能靠删除文件回收。
怎么做
第一步,确认。 执行 df -i,看 IUse% 是否 100%(或接近),同时看 IFree 是否为 0。
第二步,找出文件最多的目录。 inode 按文件计数,要找文件数量大的目录,不是体积大的:
for d in */; do echo "$(find "$d" -xdev | wc -l) $d"; done | sort -rn | head
-xdev 避免把挂载进来的其他分区算进去。对数量最多的目录继续往下执行,直到定位到具体目录。
第三步,确认能否删。 常见的是过期日志、旧缓存、临时文件、已完成的队列文件。删除前确认没有进程持有:
lsof +D /path/to/dir 2>/dev/null | head
进程持有已删除文件时,inode 不会立即释放,需重启或让进程关闭句柄。
第四步,删除并复查。 清理后再跑 df -i,IUse% 应明显下降。
怎么确认成了
touch /path/to/dir/testfile && rm /path/to/dir/testfile
不报 No space left on device 即恢复,同时 df -i 的 IFree 应大于 0。
边界和坑
- inode 不能扩容。 数量在
mkfs时定死,只能删文件或迁移到 inode 更多的文件系统。mkfs.ext4 -N是重建,不是调整。 df -h有余量不代表能写。 保留块(ext 系列默认给 root 留 5%)、磁盘配额、只读挂载都会造成同样报错,df -i只是排查第一步。- 删除大目录本身也慢。 几十万文件用
rm -rf会卡很久,可先用find dir -type f -delete分批处理。 - 容器和 overlay 要留意。 镜像层里的小文件同样占 inode,清理时别只看数据卷。
- XFS 是动态分配 inode 的,通常不会耗尽,此时
df -i参考价值有限,要回到块用量和其他原因排查。