解决 sendmail 邮件队列文件的磁盘溢出问题
最近准备重新回归运维,很好。前一阵子易先生打电话说服务器上 session 失效,他在公司又不方便 ssh 上去看。于是我为了自己的博客勉为其难上去看了一下,结果发现 /var 下面居然爆满溢出了。
www# df -h
在啧啧称赞之外,准备找出在 /var 下面所有大于 1MB 的文件:
Filesystem Size Used Avail Capacity Mounted on
/dev/ad0s1a 989M 59M 851M 7% /
devfs 1.0K 1.0K 0B 100% /dev
/dev/ad0s1d 989M 2.2M 908M 0% /tmp
/dev/ad0s1e 19G 1.6G 16G 9% /usr
/dev/ad0s1f 989M 910M -384K 100% /var
/dev/ad0s1g 124G 1.7G 113G 2% /www
/dev/ad2s1d 9.7G 1.4G 7.5G 16% /database
/dev/ad2s1e 139G 42G 85G 33% /backup
www# find /var -xdev -size +2048 -ls| sort -r +6
这个搜索结果是相当的恐怖,可以用眼花缭乱来形容当时的屏幕滚动。强行中止后发现绝大部分文件都集中在 /var/spool/clientmqueue 这个目录下面。那么这到底是个什么目录呢?
原来,当使用 sendmail 发邮件,或者系统默认要发邮件(譬如 crontab)的时候,首先会把邮件复制到这个目录里,然后等待 MTA 处理。MTA 做的事情就是把这个目录中的邮件转移到 /var/spool/mqueue,然后再发往目的地。
在 /var/spool/clientmqueue 下产生大量文件的情况,通常是因为没有合适的 MTA 来发送邮件,于是都堆积在这里了。假如这里的邮件并不是你需要的,比如由 crontab 产生的信,你可以简单地删除。
还有一种情况,当这个目录下面的文件数量足够多的时候,直接 rm -f * 的话会被提示 Argument list too long。没事,下面两个命令会帮助你搞定问题:
find /var/spool/clientmqueue/ -type f –delete
或者
find /var/spool/clientmqueue/ -type f -exec rm {} \+
不过这两条命令要求 find 的版本较新,如果你的文件版本较低,可尝试:
find /var/spool/clientmqueue/ -type f -exec rm {} \;
到这里,我们已经搞明白 /var 爆满的原因。可以判断的是,易先生服务器的问题就在于系统中有用户启用了 crontab,且 crontab 中执行的程序有输出内容。这些内容会以邮件形式发给 crontab 的用户,而 sendmail 又没有启动,所以就大量产生了这些队列文件。
解决的办法很简单,在 crontab 中命令的最后加上:
>/dev/null 2>&1
这样输出的内容会被直接抛弃,问题就得以解决了。
最后也顺便提一下禁用 sendmail 的事情。本地 MTA 正确工作是 Unix 系统正确工作的一个必要条件。盲目禁止 sendmail 意味着对安全的不关注。如果你不打算启动任何邮件服务,就不应该使用 sendmail_enable="NONE",而应使用 sendmail_enable="NO"。
当然,你也可以考虑用下面的办法来彻底消除其影响,但我认为没什么必要。在 /etc/make.conf 中加入:
NO_SENDMAIL=yes
然后 make buildworld installworld,然后用 find 删除 lib、libexec、usr/bin、usr/sbin 等目录中没有被碰过的文件,最后删除 /etc/mail、/etc/rc.d/sendmail 等文件。这个方法来源于网络,没有亲自实验,请谨慎操作。
INSTALL=install