linux 学习笔记-073-Shell 编程-告警系统邮件引擎,运行告警系统

发布于 2018-04-24  246 次阅读


告警系统邮件引擎

这里的邮件脚本需要借助于之前做 Zabbix 实验时使用过的 mail.py 脚本

脚本地址:mail.py

01:

把 mail.py 复制到存放邮件脚本的目录 mail

[root@am-01:~#] cd /usr/local/sbin/mon/mail/

[root@am-01:/usr/local/sbin/mon/mail#] cp /lib/zabbix/alertscripts/mail.py /usr/local/sbin/mon/mail/mail.py

02:

编写 mail.sh 脚本,这个脚本用作做告警收敛,收敛的目的是,服务出现问题,发一封告警邮件,之后在第十分钟的时候,服务还是出现问题,再发一封邮件,而要达到这样的效果,就需要比对两个时间之间的时间戳

[root@am-01:/usr/local/sbin/mon/mail#] vim mail.sh

log=$1

#这里的$1 其实就代表之前子脚本中发邮件那句命令的第一个参数,如

#"/bin/bash ../mail/mail.sh $addr\_502 $c_502  ../log/502.tmp",这句命令中的第一个参数就是$addr\_502

#其他子脚本同理

t_s=`date +%s`

t_s2=`date -d "2 hours ago" +%s`

#当前时间戳和两个小时前的时间戳

if [ ! -f /tmp/$log ]

then

    echo $t_s2 > /tmp/$log

fi

#判断以$1 命名的日志是否不存在,不存在则创建这个日志,并写入两个小时前的时间戳

t_s2=`tail -1 /tmp/$log|awk '{print $1}'`

#不管上面的判断有没有写入新的时间戳,都会给 t_s2 赋值,取日志的最后一行,也即是时间戳

echo $t_s>>/tmp/$log

#把当前时间的时间戳写入到日志中

v=$[$t_s-$t_s2]

#比对当前时间和之前的时间戳差值并赋值给 v

echo $v

#输出 v 的值,这个值用来判断当前时间和上次告警时间的差值,从而实现每隔多少分钟则发一次告警

if [ $v -gt 3600 ]

#判断差值是否大于一个小时

then

    ./mail.py  $1  $2  $3

    echo "0" > /tmp/$log.txt

#大于一个小时的话,直接运行发送邮件的脚本,同时新建一个用来计算告警次数的日志/tmp/$log.txt,这里称其为计>数器,这里是把这个计数器重置为 0

else

    if [ ! -f /tmp/$log.txt ]

    then

        echo "0" > /tmp/$log.txt

    fi

#如果计数器不存在,则建立一个计数器

    nu=`cat /tmp/$log.txt`

    nu2=$[$nu+1]

    echo $nu2>/tmp/$log.txt

#查看这个计数器的值 nu,并把这个值加一并赋值给 nu2,即 nu+1,最后把得出的 nu2 输出到计数器

    if [ $nu2 -gt 10 ]

    then

         ./mail.py  $1 "trouble continue 10 min $2" "$3"

         echo "0" > /tmp/$log.txt

#这里的判断是,当 nu2 的值大于 10,则发邮件,告诉用户,服务已经出问题 10 分钟了

#脚本会每分钟运行一次,每运行一次,nu 都会加 1,并赋值给 nu2

#这里发完告警邮件后,又把 0 写入到计数器,重新计数

    fi

#如果差值小于一小时,则做另一层判断

fi

03:

脚本解析

第一次告警,之前没有告警过,没执行过 mail.sh,t_s 为当前时间,t_s2 为当前时间前 2 小时,时间差为 7200 秒

那么如果$log 不存在,则把 2 小时前的时间戳写入到$log 中,也就是 7200,t_s2 为 7200,把 t_s 追加到$log 中

差值 t_s 和 t_s2 差值 v 等于 7200,大于 3600,所有发邮件告警 mail.py,并且计数 0 到$log.txt 中第一次告警结束

mail.sh 一分钟执行一次,第二次执行时

t_s2=`tail -1 /tmp/$log|awk '{print $1}'`会把 t_s2=`date -d "2 hours ago" +%s`的值覆盖掉,因此 t_s2 为 1 分钟前的时间,因为$log 为 1 分钟前,然后在追加现在时间到$log,这时差值 v 是 60,小于 3600,不告警,直接计数

那么执行 else,判断$log.txt 是否存在,第二次执行时不存在,输出计数 0 到$log.txt 中,结束判断

因此 nu=0,nu2=1,把 nu2 也就是 1 计数写入到$log.txt 中

判断 nu2 是否大于 10,那么显然不大于 10,直接结束判断,结束脚本

第三次执行时,跟第二次类似,只不过计数会变化,nu=1,nu2=2,以此类推,当 nu2>10 的时候,nu=10,nu2=11>10,那么符合 if [ $nu2 -gt 10 ]的判断,执行 mail.py 告警,并把计数器重新清为 0

如果之后没有问题,不会执行 mail.sh,如果有问题,每一分钟执行一次 mail.sh,十分钟后如果问题没有解决,再发邮件告警

运行告警系统

01:

把 main.sh 加入 crontab,一分钟执行一次

[root@am-01:/usr/local/sbin/mon/bin#] crontab -e

no crontab for root - using an empty one

* * * * * cd /usr/local/sbin/mon/bin;bash main.sh

02:

为了方便做实验,把配置文件/conf/mon.conf 的 502 监控设置为不监控

即"to_mon_502=1"设置为"to_mon_502=0"

同时把主脚本中的"exec 1>>../log/mon.log 2>>../log/err.log"注释掉

测试主脚本 main.sh 和监测系统负载的脚本 load.sh,可以见到,是没问题的

[root@am-01:/usr/local/sbin/mon/bin#] sh -x main.sh

+ export send=1

+ send=1

++ /sbin/ifconfig

++ grep -A1 'eno16777736: '

++ awk '/inet/ {print $2}'

+ export addr=172.17.1.240

+ addr=172.17.1.240

++ 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

++ date '+%F %T'

+ echo '2018-04-24 15:26:20 load average'

2018-04-24 15:26:20 load average

+ /bin/bash ../shares/load.sh

15:26:20 load is 0

+ grep -q to_mon_502=1 ../conf/mon.conf

[root@am-01:/usr/local/sbin/mon/bin#] bash ../shares/load.sh

15:26:41 load is 0

03:

mail.sh 中的$1,$2,$3 就是 mail.py 中的 to=sys.argv[1],subject=sys.argv[2],content=sys.argv[3]  三个参数,$1 发送给谁,$2 主题,$3 内容

[root@am-01:/usr/local/sbin/mon/bin#] vim ../mail/mail.sh

./mail.py  $1  $2  $3

./mail.py  $1 "trouble continue 10 min $2" "$3"

当 load.sh 的脚本检测到系统负载,那就需要发送告警邮件,也需要赋予 3 个参数,第三个参数也可以 cat,把内容作为第三个参数

这里的三个参数分别是"runfali@outlook.com","$addr\_load:$load","cat ../log/load.tmp"

[root@am-01:/usr/local/sbin/mon/bin#] vim ../shares/load.sh

/bin/bash ../mail/mail.sh runfali@outlook.com "$addr\_load:$load" `cat ../log/load.tmp`

至此,这个告警系统就完成了!