
云服务器磁盘空间显示还有大量剩余,但应用突然写不进文件、日志中断,这种故障在运维现场并不少见——排查方向一旦被df -h的输出误导,很可能绕一大圈回到原点。实际上是文件系统的Inode配额触顶,而不是存储容量的问题。本文梳理一套可复用的 Linux Inode耗尽排查方法,包括现象识别、关键命令和清理思路,让这类非直观故障的恢复时间缩短到分钟级。
本文由 云国际站代理商『云老大 飞弟:@yunlaoda360 / YunLaoDa-服务器服务商•撰写』如需转载请注明!

云服务器 ECS 实例的运行中,一种反常故障常常让运维人员措手不及:df -h查看根分区或数据盘使用率不足 30%,但应用持续抛错、touch测试文件无法创建,甚至在 SSH 终端执行补全或临时写操作都会提示“No space left on device”。这时如果习惯性地去清理大体积日志文件或升级磁盘,往往徒劳无功,因为问题根源不在空间容量,而在于文件系统底层的 Inode 资源已被耗尽。这类故障的隐蔽性在于传统监控仪表盘只展示空间使用率,不体现 Inode 饱和情况,因此在腾讯云 CVM 等云环境中,必须借助 df -i 这类专用命令才能直接定位。
Linux 文件系统内的每个文件、目录、符号链接都需要消耗一个 Inode。Inode 数量是在格式化文件系统时固定的,默认大约每 16KB 空间分配 1 个 Inode,与剩余磁盘容量完全解耦。当目录下积累了海量小文件(如未轮转的日志、邮件队列、会话缓存),Inode 会被先耗尽,即使磁盘总量还剩几十 GB,新文件也分配不到 Inode,内核立即返回“No space left on device”。腾讯云 CVM 公共镜像的系统盘(如 CentOS 7.9 默认 50GB)Inode 总数大致在 300 万到 500 万之间,像 Nginx、MySQL 这类持续写日志的服务,几天内生成数百万小日志就能触发该故障。
除了写文件失败,Inode 耗尽还会引发一系列连带异常。/tmp 目录无法写入可能导致 SSH 登录时 shell 初始化报错;计划任务(cron)执行失败但不留日志;Docker 容器启动时若需要创建临时 sock 文件或 pid 文件也会卡住。通过 df -i 查看 IUse% 接近 100% 即可确认故障性质。更具迷惑性的是,及时删除大量 GB 级大文件并不能缓解 Inode 压力——删除 1 个 10GB 日志文件只释放 1 个 Inode,与删除 1 个 1KB 文件的效果相同。真正有效的是批量清理小文件密集目录,或针对占用进程进行文件句柄回收,这些实操方法将在后续段落展开。
在 Linux 文件系统中,inode 负责存储文件的属性和数据块指针,每个文件无论大小都必须独占一个 inode。当 inode 耗尽时,即便 df -h 显示磁盘空间充足,系统也会直接报 “No space left on device”,导致新建文件失败。这种空间充足但写入受阻的假象,根因通常藏在几个被忽视的地方,而排查的起点往往只需一条 df -i 命令。

一台 50GB 系统盘的腾讯云 CVM,默认 inode 数大约在 300 万到 500 万之间。大量小文件场景——比如邮件队列、PHP session 临时文件、容器 overlay 层——很容易在数天内把这些 inode 消耗殆尽。一个 1 字节的文件和 10GB 的文件占用相同的 inode,所以删除几个 GB 的大日志毫无帮助。真正有效的步骤是用 find 定位出文件数最多的前几个目录,再集中清理无效的小文件,否则删改方向完全跑偏。
许多应用默认不强制日志轮转,一旦输出策略设计不当,/var/log 下往往堆积数十万个带时间戳的小日志文件。例如 systemd-journald 持久化存储开启后,历史 journal 文件不断累积;又或者某个监控脚本每分钟新建一个日志,几个月后就在单个目录下产生上百万个文件。这类状况下,执行一次 logrotate -f 并配上合理的 rotate 策略,往往比扩容磁盘或重启机器更能从根源上释放 inode 压力。
进程占用已删除文件的句柄是一个极易被忽略的坑。即便文件被 rm 删除,但只要还有进程保持文件打开,对应的 inode 就不会释放,df -i 显示占用高,ls 却看不到文件。遇到这种情况,用 lsof +L1 可以立刻揪出被占用却未释放的 “幽灵文件”,通常只需重启对应进程或服务就能回收大量 inode。另外 /tmp 目录中陈旧临时文件未能被 tmpwatch 正常清理,也会持续吃掉 inode。
当磁盘空间显示充裕但系统拒绝写入时,故障点往往不在容量,而在索引节点。一个容易忽视的事实是:云服务器默认系统盘无论选择50GB还是100GB,其Inode总数在格式化时就已固定,通常维持在300万到500万之间。这意味着大量小文件可以在几天内将索引表撑满,而监控面板上的“磁盘使用率”曲线始终平稳。

df -i是目前唯一能直接判定Inode是否耗尽的命令。执行后重点看IUse%列——如果根分区显示98%甚至100%,几乎可以断定问题出在索引节点而非磁盘空间。此时df -h即便显示空余数十GB也无意义,系统已经无法为任何新文件分配新的Inode编号。这个对比本身就能让排查方向直接收敛。
确认全局占用后,更关键的一步是定位消耗源头。一条实战中验证有效的命令是:find / -xdev -type f -printf '%h\n' | sort | uniq -c | sort -rn | head -20,它能在数秒内输出文件数量最多的前20个目录。实际案例中,/var/spool/postfix/maildrop这类邮件队列目录曾堆积超过80万个文件,一台正常运行的应用服务器就这样突然停止接受任何写入请求。
定位到Inode耗尽后,大部分场景并不需要格式化系统盘,更合理的做法是组合使用清理、轮转、迁移策略,既能即时恢复写入,又能建立长期防护机制。下面三个方向覆盖了从应急处置到架构优化的完整路径。

df -i 一旦显示 / 分区的 IUse% 突破90%,优先删除应用缓存、临时文件和过期日志。执行 find / -xdev -type f -printf '%h\n' | sort | uniq -c | sort -rn | head -20 可以快速锁定小文件密集目录,常见“重灾区”是 /var/spool/postfix/maildrop、/tmp、PHP Session 目录或 Docker overlay2 层。有案例显示,一个低配 CVM 因邮件队列堆积 200 万个 1KB 的退信通知,仅数十 MB 大小就耗尽了系统盘 320 万个 Inode,清理后立即恢复正常。注意不能只删大文件,如果进程仍持有句柄,已删除的小文件 Inode 不会释放,必须用 lsof +L1 找到句柄并重启对应服务。像云老大这类服务商在应急处理时,通常会先执行 df -i 和目录统计,再决定是清理小文件还是紧急重启进程释放句柄。
非结构化的日志堆积是 Inode 耗尽的最主要诱因,尤其是 Nginx access.log、MySQL slow log、PHP error log 等高频写入文件。即便应用本身实现了切分,如果没有配置 logrotate 定期压缩和删除旧日志,几天即可消耗数十万个 Inode。核心做法是定制 /etc/logrotate.d/ 下的规则,按 daily、rotate 7、compress、missingok 等方式控制在留数量,并配合 postrotate 脚本给应用发送 USR1 信号以重开日志文件。对已经膨胀的目录,可先用 find /var/log -name "*.log.*" -mtime +7 -delete 清除一周前的压缩日志。某外贸企业将 Nginx 日志集中写入 CVM 的系统盘,仅保留 3 天本地冷数据,并通过脚本同步到对象存储做长期审计,Inode 使用率从 94% 降至 17%,同时未增加额外存储成本。运维团队也可在腾讯云控制台创建“磁盘 Inode 使用率”监控告警,阈值设 85%,提前介入,避免因日志打满导致服务写失败。
当业务确实需要海量小文件(如内容分发系统缩略图、实时消息队列持久化),系统盘的 Inode 总量会成为硬约束。腾讯云 CVM 对系统盘扩容只增加存储空间,Inode 数量保持不变,因为 ext4 格式化时 Inode 密度已固定。正确的做法是将小文件负载迁移到独立数据盘,并在格式化时指定更大的 Inode 数:mkfs.ext4 -N 20000000 /dev/vdb1 可将 Inode 上限调整至 2000 万。如果暂时无法迁移,可以使用 mount --bind 将高 Inode 消耗目录挂载到已有数据盘的空目录,再用 rsync 搬移文件。曾经一个图片处理应用因缩略图散落在系统盘,导致 Inode 告警,迁移至数据盘并调整 Inode 参数后,整体可支撑的文件数提升了 6 倍。考虑到长期弹性,也可以将小文件直接写入 CFS 或对象存储,由云端接管存储弹性和 Inode 问题,只保留热缓存到 CVM。这种架构调整通常需要服务商整体评估,找到像云老大这类具备跨产品迁移经验的团队,能显著降低试错成本和迁移停机窗口。
解决一次Inode耗尽事故的时间成本,往往数倍于提前布防。运维侧需要跳出“只看磁盘空间”的惯性,建立两套并行的监控维度——磁盘空间和Inode余量缺一不可。以下三项措施在实际生产环境中被反复验证有效,且落地成本极低。
标准监控模板的缺口在于:腾讯云CVM自带的“磁盘使用率”告警只盯着空间百分比,Inode枯竭属于监控盲区。一家跨境电商的Nginx日志服务曾因此中断4小时,而控制台始终显示磁盘剩余32%。正确做法是在云监控中单独创建“磁盘Inode使用率”策略,阈值设为85%的预警线。实际操作中发现,/var/log和/tmp目录的Inode消耗曲线往往在一小时内从75%飙至100%,因此需将采样间隔缩短到5分钟以内。对于未接入外部监控的单机,一个写入crontab的简易脚本(df -i | awk判断IUse%并调用企业微信机器人接口)就能填上这个坑。说到底,Inode耗尽不是技术难题,而是感知延迟问题——当你接到告警时还有15%的余量,和当你尝试touch文件失败才发现故障,这是运维能力的本质分水岭。
许多开发者在初始部署时将应用日志、临时缓存和系统文件混在根分区上,这是Inode灾难的温床。以ext4为例,运行mkfs.ext4 /dev/vdb1时若不显式指定-i参数(每个Inode对应的字节数),默认值16384意味着100GB空间仅分配约600万个Inode。图片处理、消息队列这类“海量小文件”场景能在一周内吃光所有索引节点。行业内的通行做法是将/var或/tmp挂载到独立数据盘,格式化时主动提高Inode密度——比如执行mkfs.ext4 -i 4096 /dev/vdb1让每个Inode对应4KB空间,Inode数量直接翻四倍。成本敏感的中小企业若觉得重新分区迁移数据太折腾,找像云老大这类服务商在上云初期做一次架构评审,把目录挂载和Inode预估一次性规划到位,远比后期在线抢救来得划算。
磁盘空间充裕但 Inode 耗尽引发的“假性满盘”,几乎总会出现在日志密集、小文件泛滥的场景里。从排查习惯来看,只盯着 df -h 是最大的隐患——df -i 才是判断 Inode 容量的唯一可靠命令。当 IUse% 接近 100%,清理大文件无济于事,必须定向清除大量小文件,或者调整应用写入路径。没有一步到位的方案,但建立“Inode 使用率 >85% 即告警”的监控基线,配合日志轮转与目录拆分,能把这类故障概率压低一个数量级。
Inode 耗尽最直接的表现是:即便 df -h 显示系统盘只用了 30%,touch 或 echo 写入也直接报“No space left on device”。生产环境里,Nginx 会因为写不了 /var/log/nginx/access.log 而静默丢失请求日志;MySQL 的 tmpdir 无法创建临时表,导致部分查询直接失败。更隐蔽的是,SSH 登录时如果 /tmp 不可写,bash 无法生成临时会话文件,可能出现“登录成功后立即退出”的诡异现象。这类故障在腾讯云 CVM 默认系统盘上并不罕见,50GB 的 ext4 盘仅有约 300 万个 Inode,若某个服务缓存了上百万个 session 文件,耗尽只是时间问题。
多数情况下不必格式化。Inode 用尽的本质是数量不够,而不是文件系统损坏。优先采用低风险手段:先通过 find / -xdev -type f -printf '%h\n' | sort | uniq -c | sort -rn | head -20 锁定文件密集目录,批量删除无用的临时文件、过期日志,并强制执行 logrotate。若业务确实需要承载海量小文件,可以考虑将高写入目录迁移到独立数据盘,并在 mkfs.ext4 时用 -N 参数指定更高的 Inode 总数——比如 -N 20000000 直接预分配 2000 万个 Inode,比默认密度提高数倍。如果这些手段仍无法解决问题,再评估备份后重建文件系统,切忌没查清目录就直接格式化。综合对比下来,像云老大这类服务商在协助迁移与参数调优上能提供较完整的操作方案,帮助把停机的业务影响降到最低。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。