No space left on device:Inode 已耗尽详解

| 选择喜欢的代码风格  

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

1. 检查可用磁盘空间以确保您还有一些空间



inodes

随即发现:df -h 发现还有挺多没有用:

$ df -h

Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/xvda             33030016  10407780  22622236  32% /
tmpfs                   368748         0    368748   0% /lib/init/rw
varrun                  368748        56    368692   1% /var/run
varlock                 368748         0    368748   0% /var/lock
udev                    368748       108    368640   1% /dev
tmpfs                   368748         0    368748   0% /dev/shm
 

2. 检查 Inode


df -i 发现原来是 inodes 空间满了

$ df -i

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/xvda            2080768 2080768       0  100% /
tmpfs                  92187       3   92184    1% /lib/init/rw
varrun                 92187      38   92149    1% /var/run
varlock                92187       4   92183    1% /var/lock
udev                   92187    4404   87783    5% /dev
tmpfs                  92187       1   92186    1% /dev/shm

如果您的 IUse% 等于或接近 100%,则大量小文件是 设备上无空间 - No space left on device 错误的原因。

 

3. 接下来,运行下面命令让我们来找到他们


$ for i in /*; do echo $i; find $i |wc -l; done

最终我们发现,大量小文件是在 /var/spool/postfix 下,再进一步是藏匿在 /var/spool/postfix/maildrop,经过大量排查,终于找到了问题所在,竟然有 2486553 多个?:

[root@TestMaster /var/spool/postfix]
# for i in /var/spool/postfix/*; do echo $i; find $i |wc -l; done
/var/spool/postfix/active
1
/var/spool/postfix/bounce
1
/var/spool/postfix/corrupt
1
/var/spool/postfix/defer
1
/var/spool/postfix/deferred
1
/var/spool/postfix/flush
1
/var/spool/postfix/hold
1
/var/spool/postfix/incoming
1
/var/spool/postfix/maildrop
2486553  <--------------------------注意这里!
/var/spool/postfix/pid
1
/var/spool/postfix/private
19
/var/spool/postfix/public
6
/var/spool/postfix/saved
1
/var/spool/postfix/trace
1
 

4. 清理 /var/spool/postfix/maildrop 下的小文件


在这里用 rm 命令删除,但是失败了,提示 参数列表过长 - cannot execute [Argument list too long]发生这种情况的原因是:bash 实际上将 * 扩展到每个匹配的文件,从而产生了很长的命令行

这里使用使用 rsync 命令,来清楚这些垃圾小文件

# 创建一个临时空文件夹
mkdir /tmp/blankdir

# 清理/var/spool/postfix/maildrop
rsync -av --delete /tmp/blankdir/  /var/spool/postfix/maildrop/

# rsync选项说明:
# --delete-before 接收者在传输之前进行删除操作
# --progress 在传输时显示传输过程
# --a 归档模式,表示以递归方式传输文件,并保持所有文件属性
# --H 保持硬连接的文件
# --v 详细输出模式
# --stats 给出某些文件的传输状态

使用 rsync 时空目录的路径后要带上"/"

接下来,我们可以看到: It works!

....
deleting A34982C5D3
deleting A3497D3D8A
deleting A3497264BE0A
deleting A34971B072
deleting A3496AB2A9
deleting A349659B30
deleting A349622BBA2B
deleting A34962240B8E
deleting A3495BCC72
deleting A3495273C926
deleting A349515EEB
deleting A34946904A
deleting A34941975C2
deleting A349412E2CA3
deleting A34941053CA
deleting A349369699
deleting A34936371A
deleting A34921385D0
deleting A3491A8628F
deleting A34912D3636C
deleting A349126DDE
...

再次执行 df -i,已经有很多 Free Inodes,从 100% 降到现在的 1%:

$ df -i

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/xvda            2080768     344       0    1% /
tmpfs                  92187       3   92184    1% /lib/init/rw
varrun                 92187      38   92149    1% /var/run
varlock                92187       4   92183    1% /var/lock
udev                   92187    4404   87783    5% /dev
tmpfs                  92187       1   92186    1% /dev/shm
 

5. No space left on device - Inode 耗尽的原因分析


由于 Linux 在执行 cron 时,会将 cron 执行脚本中的 outputwarning 信息以邮件的形式发送 cron 的 owner,如果服务器上的 sendmailpostfix 没有正常运行,导致邮件发送不成功,全部小文件堆积在了 maildrop 目录下面,经历较长时间后,此目录已堆积了大量的小文件。

解决方案:在 crontab 的第一行加入 MAILTO="" 便可,这样执行当前用户的 cron 时,不会发送邮件,修改如下:

sed -i '1 i\MAILTO=""' /var/spool/cron/root

上面这种方法是治标不治本,正确做法是把对应 cron 的中执行脚本的 output 重定向到文件或 /dev/null 中。

inodes 扩展阅读:




No space left on device:Inode 已耗尽评论