服务器上部署了一批Supervisor管理的任务,每个任务在启动后会各自启动多个进程,每个进程执行不同的脚本程序。由于脚本程序实在太多了,在Supervisor里面一个个配置会极其麻烦,所以采用了这种一个任务对应多个脚本的方案。
大概就这么个意思,script.ppid = task.pid --> task.ppid = supervisor.pid。依我的文字水平只能解释到这样了,尽力了。
Supervisor是一个简单好用的工具,只要在config文件中配置了autorestart=true
,它就会在你的进程挂掉的时候自动重启,无论是task进程挂了,还是script进程挂了,Supervisor都会兢兢业业的帮你重启。于是,问题就来了,script是在task中执行了一段配置代码后启动的脚本,Supervisor自动重启的时候,怎么会知道task执行了哪段脚本配置,如何启动的script呢?没错,它不知道,也不可能知道。但是Supervisor同志真的很敬业,它即便毛都不知道它也要重启。它会执行config文件中对应的command,然后挂在task进程下作为task的子进程,和之前一样,但这个新的子进程在执行什么,不得而知,我研究了很久也不知道它启动了一个什么鬼东西。
指望Supervisor自动重启是没戏了,而祖传的框架也不能改,那就加个监控吧。Supervisor不是能知道进程挂了么,那挂了之后通知我一下咯,你不会重启我人工来重启呗。于是乎,就引入了Superlance,希望它能够在进程挂掉的时候发个邮件通知我。
Superlance是在Supervisor基础上实现的一些插件,之所以称之为高级插件,是因为“插件——Superlance”不好听,加两个字读起来顺一点,而不是因为它真的很高级。从github上来看,Superlance上次更新是2018年2月,现在已经9012年了,大概是不会再更新了。
Superlance有这么几个主要功能:
Superlance的安装异常简单,pip install superlance
就完事儿了。确认和Supervisor装在一起就行了。但是Superlance并没有白送发邮件的功能,所以想要使用邮件功能需要在服务器上装sendmail。
我是在centos下使用的,所以yum install sendmail
,同时yum install mailx
。安装完就可以用Superlance发邮件了,好了讲完了。
讲完你个菠萝西瓜棒棒锤,有些人写文章写博客就是这么写的,就跟数学书上的“显然、易知”一样可恶。这么写东西是极其不负责的,请容许我抨击一下。
首先,装完之后sendmail是不能往外发邮件的,打开sendmail的配置文件,我这里是在/etc/mail/sendmail.mc
,修改其中的DAEMON_OPTIONS
,把127.0.0.1改成0.0.0.0,然后m4 sendmail.mc > sendmail.cf
,再重启sendmail服务,这时候再试着往外发邮件。
在没有配置smtp时,服务器发出的邮件使用的邮箱是“user@host”这样的形式,是直接由服务器发出的,这类邮件会被部分邮箱当做是垃圾邮件,直接拒收。测试了一下QQ邮箱是不拒收的,所以可以用QQ邮箱先测试一下。
echo test | mail -s test [email protected]
如果正常收到的话,就可以进入下一步了。失败的话建议打开邮件服务的日志看一看,我的邮件日志在/var/log/maillog
。
接下来配置smtp,在/etc/mail.rc
中添加如下内容
set from=[email protected]
set smtp=smtp.xx.com
set smtp-auth-user=[email protected]
set smtp-auth-password=yourpassword
set smtp-auth=login
再次重启sendmail服务。重启后再次尝试发送邮件,就会发现发件人变成了你配置了smtp的邮箱,也不会被当垃圾邮件拒收了。使用的时候需要注意不要太过频繁的发送邮件,否则有些邮箱会把你的发件人邮箱封掉,别问我是怎么知道的T.T
最后,还有个坑,在mail.rc中配置了smtp,执行mail命令的时候会自动使用配置的邮件发件,但是!但是!在superlance中直接调用mail命令还是用默认服务器邮箱发件的,在command里面还是得老老实实的把smtp配置写进去。
使用Superlance是非常简单的,在原有的supervisor配置文件中添加一个事件监听即可:
[eventlistener:crashmail]
command=/usr/local/python2.7/bin/crashmail -a -m [email protected]
events=PROCESS_STATE_EXITED
redirect_stderr=true
stdout_logfile=/data/logs/listener.log
stderr_logfile=/data/logs/listener_error.log
command具体写法还是建议去官方文档仔细看一下。
完成后重启Supervisor,等待进程启动完毕后,手动找个进程kill掉,看能不能收到报警邮件,收到就OK了。
上面说收到邮件就OK了,但我一直收不到,因为我踩进了一个天坑。
我在反复失败后,在官方文档看到了这样一句话:
Crashmail is incapable of monitoring the process status of processes which are not supervisord child processes.
在文章的开头说过了,script是task的子进程,而task才是Supervisor的子进程。也就是说,不但Supervisor没法正常重启它,Superlance也不能监控它,没法报警。
Supervisor可以检测到script进程挂了,并尝试去重启它,为什么Superlance就不能检测到呢?怀着这一疑问简单看了下源码,发现当Supervisor的子进程是个多进程任务时,Supervisor发现子进程的子进程挂掉后,会重新拉起,但不会对这一事件进行输出,而Superlance的实现原理就是基于这个输出的,所以当script进程挂掉时,Superlance无法实现报警。所以Superlance的文档中每个模块下几乎都写了,只能监控Supervisor的直接子进程。而我没有仔细读文档,就掉进了这个天坑里,嘤嘤嘤。
想要Superlance监控script进程恐怕需要重写supervisor的事件输出模块才行。重写工作量太大,且难以维护,决定自行编写监控程序来实现这一功能,且听下回分解。