问题描述
中午网站突然打不开,登录阿里云控制台发现ECS的CPU占用一直在56%以上,尝试ssh登录服务器无法连接,最终只能重启。
问题排查
1. 重启服务器,ssh登录后,发现一堆sendmail进程。
/usr/sbin/sendmail -fcrondaemon -i -odi
用 /usr/sbin/sendmail -fcrondaemon
关键字作为切入口,bing搜索发现有几篇关于此问题博文,其中一篇描述是由系统计划任务(crond)引起【此时没有细读文章,还不理解,为什么是crond引起】。
2. 数据库任务记录表和php任务脚本,未排查出明显的脚本问题
3. 排查系统日志,分别查看了 /var/log/cron
, /var/log/maillog
, /var/log/messages
三个日志文件
发现 /var/log/maillog
文件,全是以下错误:
postfix/postdrop[1621814]: warning: mail_queue_enter: create file maildrop/600340.1621814: No space left on device
/var/log/messages
文件,从中午出问题时间,全是以下错误:
postdrop: warning: mail_queue_enter: create file maildrop/352345.1624052: No space left on device
4. 修改计划任务 crontab -e
报错 /tmp/crontab.rHuk45:No space left on device
通过 df -h
,显示磁盘并没有占满。但是 df -i
却显示 /dev/sda1 inodes 100%
,说明该目录文件数量已达到最大数量。
5. du -h
发现, /var/spool/postfix/maildrop
文件夹占用磁盘最大9.5GB
该目录其实是,邮件发送失败时写入的大量小文件。 这时候文件太多,就不要 cd
或 ls -la
进入该目录查看内容了,会卡死。
问题出现原因
结合搜索到的相关文章,分析出现问题的原因是:
Liunx执行crond计划任务时,当脚本(我的是php脚本)存在标准输出或标准错误输出时,会以邮件的形式通过sendmail
服务发送给cron执行者,而服务器postfix
(邮件服务) 未运行,导致发送失败,文件堆积到/var/spool/postfix/maildrop
目录,最终文件数量达到最大inodes。再如果输出信息太大会引发sendmail失败,成为僵尸进程,进程中出现一堆的/usr/sbin/sendmail -fcrondaemon -i -odi
进程,导致CPU占用过高,各项服务停摆。
问题解决方式
一、 删除 /var/spool/postfix/maildrop
下的文件
find /var/spool/postfix/maildrop/ -type f |xargs rm -rf
二、 停止计划任务,把标准输出邮件转发,以下三种种方式皆可:
编辑crond配置文件
vi /etc/crontab
,修改 MAILTO=""
修改计划任务
crontab -e
,开头增加MAILTO=""
修改计划任务,将标准输出重定向到空设备,命令行后面拼接
> /dev/null 2>&1
crontab -e
# 命令行后面拼接 > /dev/null 2>&1
php /www/think command > /dev/null 2>&1
三、 重启 crond 服务
systemctl restart crond