服务器磁盘 inode 耗尽如何处理
学完这篇,你能在服务器报 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)即可释放。
第五步:做几步预防,别让它再来一次
这一步要堵住产生源头,否则几天后又满。具体动作:
- 给所有 crontab 任务加上重定向:
* * * * * /path/script.sh > /dev/null 2>&1,或者配置MAILTO=""到/etc/crontab和/etc/cron.d/下的文件。 - 检查 logrotate:
cat /etc/logrotate.d/你的服务,确认rotate、daily、size参数合理,再跑一次logrotate -d /etc/logrotate.conf做 debug 校验。 - 应用侧限制临时文件生命周期,比如 PHP 的
session.gc_maxlifetime。 - 监控加告警:Zabbix 里对
vfs.fs.inode[/,pfree]设触发器,低于 20% 就告警;Prometheus 用node_filesystem_files_free配告警规则。 - 如果是 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 回收或日志轮转,改配置比反复清理有用。
原文链接:https://www.gj0.com/thread-241.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。