Nginx+php-fpm+MySQL的网站,有很多原因导致出现502问题,最常见的是由于php-fpm资源耗尽导致。本案例要监控的这台服务器就是这个情况,平时一直都很好,但若网站访问量很高,就会有502的状态码出现。发生502问题时,需要及时分析造成php-fpm资源耗尽的原因,所以要做一个监控脚本,当有502状态码第一时间告警通知我们。
要求如下:
1)脚本一分钟执行一次
2)监控502状态可以通过分析网站的访问日志,也可以通过用curl工具发起http请求,获得状态码,建议通过分析访问日志,假如访问日志路径为/data/logs/access.log,日志片段如下:
54.36.149.38 - [16/Sep/2018:18:21:10 +0800] www.lishiming.net "thread-5360-1-1.html" 301 "GET /thread-5360-1-1.html HTTP/1.1"-" "Mozilla/5.0(compatible;AhrefsBot/5.2; +http://ahrefs.com/robot/)"
3)一分钟出现502超过50次则需要告警
4)告警需要发邮件通知,邮箱为aming@aminglinux.com
知识点一:任务计划cron
本案例要求一分钟执行一次脚本,所以要用到cron。执行命令:
crontab -e * * * * * /bin/bash /usr/local/sbin/mon_502.sh
示例一:
每周一、三、五凌晨4点20执行脚本
/usr/local/sbin/123.sh 20 4 * * 1,3,5 /bin/bash /usr/local/sbin/123.sh
示例二:
每隔3天清空文件
/data/log/tmp.log * * */3 * * true>/data/log/tmp.log
示例三:
每天9点到12点,14点到16点执行脚本
/usr/local/sbin/xxx.sh 0 9-12,14-16 * * * /bin/bash /usr/local/sbin/xxx.sh
知识点二:过滤关键词
shell脚本中,过滤某个关键词使用grep命令,比如本例中需要把日志里包含502的日志过滤出来,命令为:
grep '502' /data/log/access.log
1)过滤出以英文字母开头的行:
grep '^[a-zA-Z]' 1.txt
2)去除所有空行:
grep -v '^$' 1.txt
3)过滤出至少有两个连续数字的行:
grep -E '[0-9][0-9]+' 1.txt 或者 grep -E '[0-9]{2,$}' 1.txt
4)过滤出含有aming或linux的有几行:
grep -Ec 'aming|linux' 1.txt
再看本案例需求,因为是一分钟检测一次,所以过滤的关键词是上一分钟的时间,通过分析日志,可以发现上一分钟可用:
date -d "-1 min" +%d/%m/%Y:%H:%M:[0-5][0-9]
这个关键词来表示。[0-5][0-9]就是对59秒的匹配。
知识点三:shell中的变量
如果要比较的对象不是数字,而是一个字符串的时候,可以这样用:
if [$str == "aminglinux"]
当变量str的值是aminglinux的时候。
知识点四:在命令行下发邮件
用一个Python发邮件的脚本,调用第三方邮件,用的是163邮箱。手机可以安装客户端,所以不用担心提醒的问题。接收邮件人可以是自己,就是自己给自己发邮件,这样也不会有垃圾邮件的烦恼。
发邮件的Python脚本:
mail.py
#!/bin/bash #coding:utf-8 import smtplib from email.mime.text import MIMEText import sys mail_host = 'smtp.163.com' mail_user = 'test@163.com' mail_pass = 'your_mail_password' mail_postfix = '163.com' def send_mail(to_list,subject,content): me = "zabbix告警平台"+"<"+mail_user+"@"+mail_postfix+">" msg = MIMEText(content, 'plain', 'utf-8') msg['subject'] = subject msg[from] = me msg['to'] = to_list try: s = smtplib.SMTP() s.connect(mail_host) s.login(mail_user,mail_pass) s.sendmail(me,to_list,msg.as_string()) s.close() return True expect Exception,e: print str(e) return False if _name_ == "_main_": send_mail(sys.argv[1],sys.argv[2],sys.argv[3])
说明:
该脚本会用到第三方的邮箱账户,需要填写正确的mail_host,mail_user和mail_pass。脚本名字为mail.py,发邮件的命令为:
python mail.py aming@aminglinux.com "邮件主题" "邮件内容"
本案例参考脚本:
vim /usr/local/sbin/mon_502.sh
#!/bin/bash ##该脚本用来监控网站的502问题 ##作者: ##日期: ##版本:v0.1 #[0-5][0-9]表示59秒内任何数字,就是前一分钟任何秒数的日志或文件。 t=`date -d "-1 min" +%d/%m/%Y:%H:%M:[0-5][0-9]` log="/data/logs/access.log" #假设mail.py已写好,并放在/usr/local/sbin/下 mail_script="/usr/local/sbin/mail.py" mail_user=aming@aminglinux.com n=`grep $t $log|grep -c "502"` if [ $n -gt 50 ] then python $mail_script $mail_user "网站有502" "一分钟内出现了$n次" fi
增加任务计划:
* * * * * /bin/bash /usr/local/sbin/mon_502.sh 2>/tmp/mon_502.err
说明:
需要在该cron最后面定义一个错误日志输出,如果脚本执行过程中有报错,我们可以到/tmp/mon_502.err文件中查看错误信息。