登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux 磁盘空间没满但仍写不进去:inode 用尽的定位、清理与复测

来源:17golang原创

时间:2026-07-26 17:44:22 317浏览 收藏

有些 Linux 故障很容易被 df -h 误导:磁盘还剩几十 GB,应用却在创建临时文件时直接报 No space left on device。这通常是 inode 用完了——容量统计看的是字节,inode 统计的是文件、目录等文件系统对象的数量。

先用 df -i 看 inode 使用率,再定位小文件最多的目录;确认无业务风险后清理,最后用同一组命令复测容量、inode 和服务写入。

要点速览
  • df -h 正常不代表还能创建文件,df -i 才能确认 inode 是否耗尽。
  • 定位时先从挂载点和一级目录入手,不要直接对整个根目录执行高风险删除。
  • 日志切割、缓存碎片和临时文件是小文件爆发的常见来源,清理策略要保留最近可用数据。
  • 复测不能只看容量,至少还要检查 inode、应用写入和服务日志。

为什么磁盘还有空间,mkdir 仍然会失败

文件系统创建一个新文件时,需要同时分配数据块和 inode。前者存放文件内容,后者记录权限、所有者、时间和数据块位置。小文件很多时,数据块可能还没用尽,inode 却先到达上限。

先看两个指标,不要急着改日志配置:

df -hT /var
df -i /var
findmnt -T /var

如果 df -iIUse% 接近 100%,而 df -h 仍有余量,方向就很明确了。findmnt 用来确认目标路径实际落在哪个挂载点,避免把清理范围误判成整个根分区。

Linux df -h 与 df -i 对照,/var 挂载点从 inode 满载指向小文件定位

用一组低风险命令找出小文件堆积点

排查的第一步是找“哪个挂载点满”,第二步才是找“哪个目录制造了大量对象”。下面的命令只统计,不删除:

df -iP | sort -k5 -h

sudo find /var -xdev -type f -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -nr | head -20

-xdev 很关键,它让 find 不跨到其他文件系统;否则挂载在 /var 下的目录也可能被算进来,结果既慢又容易误导。第二条命令按文件所在目录计数,通常能很快暴露出某个缓存目录、临时目录或日志碎片目录。

如果需要知道目录体积,再单独检查候选路径:

sudo du -xhd1 /var 2>/dev/null | sort -h
sudo find /var/cache/my-service -xdev -type f | wc -l
sudo find /var/cache/my-service -xdev -type f -printf '%TY-%Tm-%Td %p\n' | sort | head -20

这里不要只盯着最大的目录。一个占用 2 GB 的目录可能只有几百个大文件,而另一个只有 800 MB 的目录可能塞了数百万个几 KB 的碎片文件,后者才是 inode 的主要消耗者。

清理顺序:先止住增长,再处理可重建数据

清理前先确认候选目录属于谁、是否仍在写入。对正在增长的日志或队列目录直接删除,可能导致应用句柄指向已删除文件,甚至丢掉仍未消费的任务。

更稳妥的顺序是:

  1. 先暂停制造碎片文件的定时任务或降低写入速率,并记录当前 inode 使用率。
  2. 优先处理明确可重建的缓存、过期临时文件和已经上传到集中日志系统的旧日志。
  3. 使用应用自带清理命令或日志轮转;必须手动删除时,限定绝对路径、文件类型和时间范围。
  4. 清理后立即复测,不要一次性扩大删除范围。
# 示例:只列出 14 天前的缓存文件,先看清单
sudo find /var/cache/my-service -xdev -type f -mtime +14 -print | head -50

# 确认清单无误后再删除;生产环境应配合维护窗口
sudo find /var/cache/my-service -xdev -type f -mtime +14 -delete

如果是日志问题,优先检查 logrotate 是否正常运行、轮转后的压缩文件是否仍然产生过多分片,以及应用是否持有已删除的大日志。后者可以通过 lsof +L1 发现:文件名已经消失,但进程仍占着空间;它主要影响容量,不一定解决 inode 问题,却经常和这类故障一起出现。

Linux 小文件目录经过限范围清理后,inode 使用率下降并通过写入复测

用前后指标确认修复真的生效

清理完成后,至少保存下面四项结果。单看 df -h 变绿,只能说明数据块释放了,不能证明 inode 或业务写入已经恢复。

检查项修复前关注修复后应看到
挂载点findmnt -T /var 结果路径和文件系统没有误判
inodeIUse% 接近 100%有明显余量,且不再持续上升
文件创建mkdir 或临时文件报错测试目录可创建、删除
服务状态日志出现 No space left on device新请求能写日志或落盘
test_dir=/var/tmp/inode-recheck-$$
mkdir "$test_dir" && touch "$test_dir/probe" && rm -f "$test_dir/probe" && rmdir "$test_dir"
df -iP /var
tail -n 50 /var/log/my-service/app.log

如果 inode 很快再次上涨,问题不是“还没删干净”,而是增长源仍在运行。把刚才的目录计数命令加入短时间观察,结合 find 输出的文件名模式,回到日志轮转、缓存过期或临时文件清理策略上处理根因。

几个容易把故障越修越大的误区

rm -rf /var/* 当作快速修复

这种做法无法区分缓存、队列、配置和运行时目录,风险远高于 inode 故障本身。先确定挂载点和具体目录,再用时间、后缀或文件名模式收窄范围。

只看目录大小,不看文件数量

du -sh 适合找容量大户,不能替代 inode 统计。文件数量要用 find ... | wc -l 或按目录聚合的计数命令确认。

删除日志后立刻重启所有服务

重启可能释放被删除文件占用的容量,却不能修复仍在持续生成小文件的配置。先找到增长源,再决定是否需要重启或滚动重载。

相关问题

inode 用完一定是小文件太多吗?

通常是,但也可能是某个程序反复创建临时文件却没有及时清理。用目录级文件计数和文件名模式确认,不要只凭目录体积猜测。

清理 inode 后 df -h 为什么变化不大?

因为你释放的主要是 inode,不一定释放了很多数据块。只要 df -i 恢复且业务可以创建文件,容量变化小并不代表清理失败。

能不能通过扩容解决 inode 不够?

单纯扩大虚拟磁盘未必增加当前文件系统的 inode 数量。应先确认文件系统类型和扩容方式;短期先止住小文件增长,长期再调整存储设计。

总结:把容量和对象数量分开看

Linux 写不进文件时,df -h 只是一个入口。先用 df -i 判断 inode,再用不跨挂载点的统计命令锁定小文件目录,按可重建数据、时间范围和业务状态逐步清理,最后用创建文件、inode 和服务日志做闭环验证。这套顺序比“看到报错就删目录”慢不了多少,却能显著降低误删风险。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>