案例二、监控Nginx服务器状态码是否有502

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文件中查看错误信息。



上一篇:Pat-甲-1105(Spiral Matrix -螺旋矩阵)


下一篇:await 和 Task.Wait() 的异同点