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
df -h
是有足够空间,df -i
才发现原来是 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
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 错误的原因。
$ 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
在这里用 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
由于 Linux 在执行 cron 时,会将 cron 执行脚本中的 output
和 warning
信息以邮件的形式发送 cron 的 owner,如果服务器上的 sendmail
或 postfix
没有正常运行,导致邮件发送不成功,全部小文件堆积在了 maildrop 目录下面,经历较长时间后,此目录已堆积了大量的小文件。
解决方案:在 crontab 的第一行加入 MAILTO=""
便可,这样执行当前用户的 cron 时,不会发送邮件,修改如下:
sed -i '1 i\MAILTO=""' /var/spool/cron/root
上面这种方法是治标不治本,正确做法是把对应 cron 的中执行脚本的 output 重定向到文件或 /dev/null
中。