磁盘有空间却写不进文件,先用 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 参考价值有限,要回到块用量和其他原因排查。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注