服务器磁盘 inode 耗尽如何处理

域名注册
域名注册 正式会员超兽战士 👑年卡会员
发布于 2026-10-07 10:51 ·0 浏览 ·0 回复

学完这篇,你能在服务器报 No space left on device 但 df -h 显示还有空间时,快速确认是不是 inode 耗尽,定位到具体目录,安全地清掉海量小文件,并做几步预防避免复发。

第一步:先确认到底是不是 inode 满了

这一步要做的是区分「磁盘容量满」和「inode 数量满」,因为两者的处理方式完全不同。执行:

df -h
df -i

df -h 看的是 block 空间,df -i 看的是 inode 使用量。如果 df -h 里某个分区还剩几十 G,但 df -i 里该分区的 IUse% 显示 100%,IFree 接近 0,那就是 inode 耗尽。典型报错是 touch: cannot touch 'a.txt': No space left on device,写入失败但空间明明够。

注意:别看到报错就急着删大文件。inode 是被「文件个数」消耗的,一个 10G 的大日志只占 1 个 inode,反而 100 万个 1KB 的小文件能吃掉 100 万个 inode。删错方向等于白干。

第二步:找到哪个目录小文件最多

这一步要算出每个一级目录下的文件总数,锁定重灾区。先看每个挂载点下的一级目录:

for d in /var /home /tmp /usr /opt; do
  echo -n "$d  "
  find $d -xdev -type f 2>/dev/null | wc -l
done

更快的办法是按父目录聚合计数:

find / -xdev -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -rn | head -20

第一列数字最大的那个目录,就是小文件聚集地。-xdev 是必须的,它能防止 find 跨到别的挂载点,也顺手避开了 /proc、/sys 这些遍历会卡死的地方。

注意:find / 全盘扫描在 inode 已满时可能跑几分钟到十几分钟。先按可疑目录分批扫,比如先扫 /var 再扫 /home,不要一上来就全盘。如果服务器已经卡到打不开新进程,优先扫最可能的地方。

第三步:进到具体目录,看清是什么文件

这一步要确认文件类型,避免误删业务数据。假设重灾区是 /var/spool/postfix/maildrop:

cd /var/spool/postfix/maildrop
ls -1 | wc -l
ls -f | head -20

ls -f 不排序、不统计,在几十万文件时比普通 ls 快得多。常见的 inode 杀手有这么几类:

  • /var/spool/postfix/maildrop 或 /var/spool/clientmqueue:cron 任务有输出但没配邮件发送,每条输出攒一个文件。
  • /var/lib/php/session:session 回收机制失效。
  • 各类应用的上传临时目录、缩略图缓存目录、data/tmp。
  • 日志轮转配置写错,日志没被切割而是每天新生成一堆小文件。

第四步:用 find 批量删除

这一步要清空这些文件并释放 inode。用 find 的 -delete:

find /var/spool/postfix/maildrop -type f -name '*' -delete

如果只想删 7 天前的:

find /var/spool/postfix/maildrop -type f -mtime +7 -delete

删除完成后确认结果:

df -i

IUse% 应该明显下降。

注意:千万不要用 rm -rf /path/*,几十万文件会触发 Argument list too long 报错,删不掉还刷屏。也不要用 rm -rf * 这种带通配符的写法删不确定的目录。删之前先 pwd 确认路径,再用 ls -1 | wc -l 看数量级,心里有数再动手。

注意:如果进程还握着已删除文件的句柄,inode 不会立刻回收。用 lsof +L1 查看,找到 PID 后重启对应服务(如 systemctl restart postfix)即可释放。

第五步:做几步预防,别让它再来一次

这一步要堵住产生源头,否则几天后又满。具体动作:

  1. 给所有 crontab 任务加上重定向:* * * * * /path/script.sh > /dev/null 2>&1,或者配置 MAILTO="" 到 /etc/crontab 和 /etc/cron.d/ 下的文件。
  2. 检查 logrotate:cat /etc/logrotate.d/你的服务,确认 rotate、daily、size 参数合理,再跑一次 logrotate -d /etc/logrotate.conf 做 debug 校验。
  3. 应用侧限制临时文件生命周期,比如 PHP 的 session.gc_maxlifetime。
  4. 监控加告警:Zabbix 里对 vfs.fs.inode[/,pfree] 设触发器,低于 20% 就告警;Prometheus 用 node_filesystem_files_free 配告警规则。
  5. 如果是 XFS 且确实需要更多 inode,可以在线提高百分比:xfs_growfs -m 25 /挂载点(把 imaxpct 提到 25)。ext4 无法在线增加 inode 总数,只能备份数据后重建文件系统,mkfs.ext4 -i 4096 可以调小每 inode 对应的字节数来换取更多 inode。

小结

  • 判断标准是 df -i 的 IUse%,不是 df -h。
  • 定位用 find / -xdev -printf '%h\n' | sort | uniq -c | sort -rn | head,-xdev 不能省。
  • 删除用 find ... -delete,不要用 rm -rf *。
  • 删完记得用 lsof +L1 检查是否有进程占着句柄不放。
  • 根因八成是 cron 输出、session 回收或日志轮转,改配置比反复清理有用。
版权声明:本文来自 GJ站长论坛《服务器磁盘 inode 耗尽如何处理》
原文链接:https://www.gj0.com/thread-241.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~