[toc]
shell 项目 - 告警系统
[ ] 要求: 我们的机器角色多种多样, 但是所有机器上都要部署同样的监控系统, 也就说所有机器不管什么角色, 整个程序框架都是一致的, 不同的地方在于根据不同的角色, 定制不同的配置文件.
[ ] 程序架构:
[x] bin 下是主程序;
[x] conf 下是配置文件;
[x] shares 下是各个监控脚本;
[x] mail 下是邮件引擎;
[x] log 下是日志.
五, 邮件引擎
一旦之前所设定的部分监控脚本超出了设定的值, 我们需要进行报警.
5.1 告警系统(核心配置) mail.sh(告警收敛)
- log=$1 //log 作为一个变量, 接收来自第一个参数的值
- t_s=`date +%s` // 时间戳
- t_s2=`date -d "2 hours ago" +%s` // 两个小时前的时间戳
- if [ ! -f /tmp/$log ] // 如果日志文件不存在
- then
- echo $t_s2> /tmp/$log // 把两个小时前的时间戳写到日志第一行, 从下往上写
- fi
- t_s2=`tail -1 /tmp/$log|awk '{print $1}'` // 截取时间戳, 最后一行
- echo $t_s>>/tmp/$log // 追加当前时间戳, 写入
- v=$[$t_s-$t_s2] // 时间戳的时间差 (以秒为单位) 详情如下
- echo $v
- if [ $v -gt 3600 ] // 此处的 if 判断是, 当过了 1 小时如果还是没有恢复再次发告警邮件. 调用 mail.py(如果没有恢复, 每 1 小时发一次)
- then
- ./mail.py $1 $2 $3 // 告警
- echo "0"> /tmp/$log.txt // 生成一个新的. txt 日志. 用来记录告警
- else
- if [ ! -f /tmp/$log.txt ] // 判断有没有这个日志文件(计数器文件)
- then
- echo "0"> /tmp/$log.txt // 计数器归零
- fi
- nu=`cat /tmp/$log.txt` // 查看计数器的数字
- nu2=$[$nu+1] // 计数器 + 1
- echo $nu2>/tmp/$log.txt // 把计数器写入日志文件(重置)
- if [ $nu2 -gt 10 ]
- then
- ./mail.py $1 "trouble continue 10 min $2" "$3" // 代表着已经持续了 10 分钟了
- echo "0"> /tmp/$log.txt // 重新归零开始计数
- fi
- fi
5.2 脚本详细解析:
[ ] 为什么以秒为单位呢? 这就涉及到了 "告警收敛", 脚本是每隔一分钟执行一次的, 如果触发了就告警, 如果短时间搞定或者告警数量很多, 告警信息就会影响你解决分析判断问题, 如果成千上百台机器, 那就是太多了
[ ] 如果脚本开始报警, log 的 $1 是什么? 还记得上篇文章当报警的时候执行 mail.sh 紧接着给了个参数, 那个参数就是所谓的 $1.t_s 时间戳 t_s2 2 小时之前的时间戳, 定义两小时的原因就是为了执行下面的 if 语句, 条件成立就实现了咱们的报警条件, 开始报警.
[ ] 发了邮件后, 写一个计数器在 log.txt 中, else 我们现在就不执行了, 因为那是小于 3600 才执行的东西.
[ ] 脚本每分钟执行一次, 第二次开始, log,t_s,t_s2 相对于第一次只是增加了一分钟, 判断文件是否存在, 因为上一次刚刚执行过, 所以一定是存在的, t_s2 就只是增加了 60s 所以经过提取给变量 v, 判断不超过 3600, 开始执行 else 的内容, 第一次执行的时候已经创建了 log.txt 所以是有的且 nu 为 0 nu2 为 1,nu2 不大于 10, 所以就是再次循环 .
[ ] 直到执行到最后一步 nu2 为 11 了, 那也就是到了 10 分钟了, 如果故障还是存在, 运维再次收到一个告警邮件, 故障已经持续 10 分钟了. 这样就实现了咱们所说的 "告警收敛"
[ ] 如果超过 10 分钟再次发了邮件, 然后执行计数器归 0, 再次开始重新循环计数.
[ ] 最后告警解除了, 不再调用 mail.sh, 也就恢复了, 不在执行 mail.sh 了.
[ ] 假如脚本在执行 3 分钟的时候, 突然故障恢复了, 脚本也就不会再次执行, 然后计数器保持在 2, 在计数周期内如果恢复, 不告警即不发邮件, 但只有在一个小时以后故障才会消失, 大于 3600 的, 如果在一个小时内再次报警, 还是按照之前的计数器继续执行!
5.3 发邮件 python 脚本 mail.py
- #!/usr/bin/env python
- #-*- coding: UTF-8 -*-
- import os,sys
- reload(sys)
- sys.setdefaultencoding('utf8')
- import getopt
- import smtplib
- from email.MIMEText import MIMEText
- from email.MIMEMultipart import MIMEMultipart
- from subprocess import *
- def sendqqmail(username,password,mailfrom,mailto,subject,content):
- gserver = 'smtp.qq.com'
- gport = 25
- try:
- msg = MIMEText(unicode(content).encode('utf-8'))
- msg['from'] = mailfrom
- msg['to'] = mailto
- msg['Reply-To'] = mailfrom
- msg['Subject'] = subject
- smtp = smtplib.SMTP(gserver, gport)
- smtp.set_debuglevel(0)
- smtp.ehlo()
- smtp.login(username,password)
- smtp.sendmail(mailfrom, mailto, msg.as_string())
- smtp.close()
- except Exception,err:
- print "Send mail failed. Error: %s" % err
- def main():
- to=sys.argv[1]
- subject=sys.argv[2]
- content=sys.argv[3]
- ## 定义 QQ 邮箱的账号和密码, 你需要修改成你自己的账号和密码(请不要把真实的用户名和密码放到网上公开, 否则你会死的很惨)
- sendqqmail('1234567@qq.com','aaaaaaaaaa','1234567@qq.com',to,subject,content)
- if __name__ == "__main__":
- main()
- ##### 脚本使用说明 ######
- #1. 首先定义好脚本中的邮箱账号和密码
- #2. 脚本执行命令为: python mail.py 目标邮箱 "邮件主题" "邮件内容"
5.4 运行告警系统
5.4.1 脚本加入 crontab 每分钟执行一次
*/1 * * * * cd /usr/local/sbin/mon/bin; bash main.sh
5.4.2 执行 main.sh, 确定最终结果
- [root@xavi mail]# cd /usr/local/sbin/mon/bin/
- [root@xavi bin]# sh -x main.sh
- + export send=1
- + send=1
- ++ grep -A1 'ens33:'
- ++ /sbin/ifconfig
- ++ awk '/inet/ {print $2}'
- + export addr=192.168.72.130
- + addr=192.168.72.130
- ++ pwd
- + dir=/usr/local/sbin/mon/bin
- ++ echo /usr/local/sbin/mon/bin
- ++ awk -F/ '{print $NF}'
- + last_dir=bin
- + '[' bin == bin ']'
- + conf_file=../conf/mon.conf
- + exec
查看错误日志:
- [root@xavi bin]# cat ../log/err.log
- ++ date '+%F %T'
- + echo '2018-04-25 23:40:33 load average'
- + /bin/bash ../shares/load.sh
- + grep -q to_mon_502=1 ../conf/mon.conf
- ++ grep logfile= ../conf/mon.conf
- ++ awk -F = '{print $2}'
- ++ sed 's///g'
- + export log=/data/log/xxx.xxx.com/access.log
- + log=/data/log/xxx.xxx.com/access.log
- + /bin/bash ../shares/502.sh
grep: /data/log/xxx.xxx.com/access.log: 没有那个文件或目录
根据错误提醒修改部分参数设置:
[root@xavi bin]# vi ../conf/mon.conf
[root@xavi bin]# vi main.sh
load 的测试已经成功
邮件发送不再演示了, 在配置到线上过程时, 一定要保持各项的参数配置符合现场的需求或者设置
来源: http://blog.51cto.com/12995218/2107907