目录
Shell项目-告警系统
一.整体流程:
1.需求:
使用shell定制各种个性化告警工具,但需要统一化管理、规范化管理。
2.思路:
指定一个脚本包,包含主程序、子程序、配置文件、邮件引擎、输出日志等。
3.主程序:
作为整个脚本的入口,是整个系统的命脉。
4.配置文件:
是一个控制中心,用它来开关各个子程序,指定各个相关联的日志文件。
5.子程序:
这个才是真正的监控脚本,用来监控各个指标。
6.邮件引擎:
是由一个python程序来实现,它可以定义发邮件的服务器、发邮件人以及发件人密码
7.输出日志:
整个监控系统要有日志输出。
二.目录结构与要求:
1.要求:
我们的机器角色多种多样,但是所有机器上都要部署同样的监控系统,也就说所有机器不管什么角色,整个程序框架都是一致的,不同的地方在于根据不同的角色,定制不同的配置文件。
2.程序架构:
#bin下是主程序
#conf下是配置文件
#shares下是各个监控脚本
#mail下是邮件引擎
#log下是日志
三.创建主目录和子目录
在/usr/local/sbin/目录下创建主目录mon,然后在主目录mon下创建各个子目录
[root@localhost ~]# cd /usr/local/sbin
[root@localhost sbin]# mkdir mon
[root@localhost sbin]# cd mon
[root@localhost mon]# mkdir bin conf shares mail log
四.告警系统主脚本
1.告警系统main.sh
首先我们要编写一个告警系统的主脚本,这个主脚本的文件名称为main.sh,这里我们将这个脚本文件放在我们刚刚创建的/usr/local/sbin/mon/bin目录下然后编写main.sh脚本,main.sh内容如下:
[root@localhost mon]# vi bin/main.sh
[root@localhost mon]# cat bin/main.sh
#!/bin/bash
#Written by aming.
# 是否打开发送邮件的开关,1为打开
export send=1
# 过滤ip地址,为了告诉我们发送邮件的IP,注意这里的网卡名称要改为你的网卡名称
export addr=`/sbin/ifconfig |grep -A1 "ens33: " |awk '/inet/ {print $2}'`
# 定义邮箱地址和授权码
export EMAIL_USERNAME='486186398@qq.com'
export EMAIL_PASSWORD='xxxxxxxxxxxxxxxx'
export EMAIL_FROM='486186398@qq.com'
# 把当前路径拿出来
dir=`pwd`
# 只需要最后一级目录名
last_dir=`echo $dir|awk -F'/' '{print $NF}'`
# 下面的判断目的是,保证执行脚本的时候,我们在bin目录里,不然监控脚本、邮件和日志很有可能找不到
if [ $last_dir == "bin" ] || [ $last_dir == "bin/" ]; then
# 定义配置文件所在的路径
conf_file="../conf/mon.conf"
else
# 如果不在bin目录下就退出整个脚本
echo "you shoud cd bin dir"
exit
fi
# 输出正确日志和错误日志
exec 1>>../log/mon.log 2>>../log/err.log
# 给日志记录标记一个时间,还有系统负载
echo "`date +"%F %T"` load average"
# 执行load.sh子脚本
/bin/bash ../shares/load.sh
#先检查配置文件中是否需要监控502.sh
if grep -q 'to_mon_502=1' $conf_file; then
# 过滤出在配置文件中定义的日志文件路径
export log=`grep 'logfile=' $conf_file |awk -F '=' '{print $2}' |sed 's/ //g'`
/bin/bash ../shares/502.sh
fi
五.告警系统配置文件
1.告警系统mon.conf
主脚本编写完之后,就是编写配置文件,配置文件比较简单里面主要就是一些定义开关的开启关闭状态和日志文件路径等内容。配置文件要放在/usr/local/sbin/mon/conf/下,文件名称必须为mon.conf,因为在主脚本里已经定义了,mon.conf文件的内容如下:
[root@localhost mon]# vi conf/mon.conf
[root@localhost mon]# cat conf/mon.conf
## to config the options if to monitor
## 定义mysql的服务器地址、端口以及user、password
to_mon_cdb=0 ##0 or 1, default 0,0 not monitor, 1 monitor
db_ip=192.168.77.11
db_port=3306
db_user=root
db_pass=123456
## httpd 如果是1则监控,为0不监控
to_mon_httpd=0
## php 如果是1则监控,为0不监控
to_mon_php_socket=0
## http_code_502 需要定义访问日志的路径
to_mon_502=1
# 定义日志文件路径
logfile=/var/log/nginx/access.log
## request_count 定义是否监控请求数量
to_mon_request_count=0
# 定义请求日志的路径
req_log=/var/log/nginx/access.log
# 定义域名
domainname=192.168.77.11
配置文件的参数可以自定义,本身配置文件就是用来给用户定义的。
六.告警系统监控项目
1.告警系统load.sh
编写子脚本,也就是监控项目,这个load.sh子脚本是必须要有的,这个脚本用来监控系统负载,因为在主脚本里已经定义了需要执行这个子脚本来进行监控系统负载。这个脚本需要放在/usr/local/sbin/mon/shares/ 目录下,而且以后的子脚本都是放在这个目录下,因为主脚本里已经定义了,load.sh内容如下:
[root@localhost mon]# vi shares/load.sh
[root@localhost mon]# cat shares/load.sh
#! /bin/bash
# 定义load的值
load=`uptime |awk -F 'average:' '{print $2}'|cut -d',' -f1|sed 's/ //g' |cut -d. -f1`
# 判断系统负载是否高于预设值和发送邮件的开关是否打开
if [ $load -gt 10 ] && [ $send -eq "1" ]
then
# 输出一条日志记录,这个日志会作为邮件内容
echo "$addr `date +%T` load is $load" >../log/load.tmp
# 执行发邮件的脚本,这里的邮箱地址写你的邮箱地址
/bin/bash ../mail/mail.sh 486186398@qq.com "$addr\_load:$load" `cat ../log/load.tmp`
fi
# 输出日志到主脚本中指定的日志文件
echo "`date +%T` load is $load"
2.告警系统502.sh
这个脚本用于监控502状态码发生的次数。502.sh内容如下:
[root@localhost mon]# vi shares/502.sh
[root@localhost mon]# cat shares/502.sh
#! /bin/bash
# 截取一分钟以前的时间
d=`date -d "-1 min" +%H:%M`
# 获得502状态码发生的次数
c_502=`grep :$d: $log |grep ' 502 '|wc -l`
# 次数大于预设值,并且发送邮件的开关为打开状态,就发送告警邮件
if [ $c_502 -gt 10 ] && [ $send == 1 ]; then
# 记录日志信息作为告警邮件的内容
echo "$addr $d 502 count is $c_502">../log/502.tmp
# 调用发送邮件的脚本
/bin/bash ../mail/mail.sh 486186398@qq.com "$addr\_502:$c_502" `cat ../log/502.tmp`
fi
# 记录日志
echo "`date +%T` 502 $c_502"
3.告警系统disk.sh
这个脚本是用来监控磁盘使用率的,这个脚本会把每个磁盘分区每个都看一下。disk.sh内容如下:
[root@localhost mon]# vi shares/disk.sh
[root@localhost mon]# cat shares/disk.sh
#! /bin/bash
# 先删除之前记录的日志文件
rm -f ../log/disk.tmp
# 先把环境语言改为英文,因为是按照英文来进行过滤的
LANG=en
# 遍历出df -h 命令结果中为已用那一列的百分比数字
for r in `df -h |awk -F '[ %]+' '{print $5}'|grep -v Use`
do
# 如果有分区的已用率大于90就记录日志
if [ $r -gt 90 ] && [ $send -eq "1" ]
then
echo "$addr `date +%T` disk useage is $r" >>../log/disk.tmp
fi
# 判断日志文件是否存在
if [ -f ../log/disk.tmp ]
then
# 文件存在就发送邮件
df -h >> ../log/disk.tmp
/bin/bash ../mail/mail.sh 486186398@qq.com "$addr\_disk:$r" `cat ../log/disk.tmp`
echo "`date +%T` disk useage is nook"
else
# 不存在则记录日志
echo "`date +%T` disk useage is ok"
fi
done
七.告警系统邮件引擎
1.告警系统mail.sh
在编写mail.sh之前,先得准备一个发送邮件的功能性脚本,因为这个告警系统会在监控项出现问题的时候发送告警邮件,所以还需要编写一个能够发送邮件的脚本,我这里使用的脚本是python编写的,这个脚本放在/usr/local/sbin/mon/mail 目录下:
#我这里用的是python3格式
[root@localhost mon]# vi mail/mail.py
[root@localhost mon]# cat mail/mail.py
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import sys
import argparse
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import logging
# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def sendqqmail(username, password, mailfrom, mailto, subject, content):
# 这里要修改为你邮箱的smtp服务地址,例如qq邮箱的话,就是smtp.qq.com
gserver = 'smtp.qq.com'
gport = 25
try:
msg = MIMEText(content, 'plain', 'utf-8')
msg['From'] = mailfrom
msg['To'] = mailto
msg['Subject'] = subject
smtp = smtplib.SMTP(gserver, gport)
smtp.set_debuglevel(0)
smtp.ehlo()
smtp.starttls() # 启用TLS加密
smtp.login(username, password)
smtp.sendmail(mailfrom, mailto, msg.as_string())
smtp.quit()
logging.info("邮件发送成功")
except Exception as err:
logging.error(f"邮件发送失败: {err}")
def main():
parser = argparse.ArgumentParser(description="发送邮件工具")
parser.add_argument("to", help="收件人邮箱地址")
parser.add_argument("subject", help="邮件主题")
parser.add_argument("content", help="邮件内容")
args = parser.parse_args()
# 从环境变量中读取敏感信息
username = os.getenv('EMAIL_USERNAME')
password = os.getenv('EMAIL_PASSWORD')
mailfrom = os.getenv('EMAIL_FROM')
if not all([username, password, mailfrom]):
logging.error("缺少必要的环境变量")
sys.exit(1)
sendqqmail(username, password, mailfrom, args.to, args.subject, args.content)
if __name__ == "__main__":
main()
这里所需的邮箱账号、地址、密码定义在主脚本main.sh中。想要修改邮箱可以去主脚本main.sh中修改。
然后再编写mail.sh脚本,这个脚本是做告警收敛的,因为之后会设定1分钟进行监控一次,所以主要用于控制当告警持续了10分钟后才发送告警邮件,这个脚本和mail.py一样也是放在mail/目录下,脚本内容如下:
[root@localhost mon]# vi mail/mail.sh
[root@localhost mon]# cat mail/mail.sh
#!/bin/bash
# 拿到当前脚本的第一个参数,也就是之前在子脚本中定义的监控项的标识与机器IP
log=$1
# 当前的时间戳
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 ]
then
# 就发送告警邮件
python3 ../mail/mail.py $1 $2 $3
# 并且生成一个新的日志,用于记录告警持续的次数
echo "0" > /tmp/$log.txt
else
# 时间差小于一小时就代表不是第一次告警了,所以判断一下log.txt文件是否存在
if [ ! -f /tmp/$log.txt ]
then
# 不存在就生成一个
echo "0" > /tmp/$log.txt
fi
# 拿出log.txt文件的内容
nu=`cat /tmp/$log.txt`
# 进行计数
nu2=$[$nu+1]
# 然后再写入到log.txt中,其实这个文件就相当于是一个计数器
echo $nu2>/tmp/$log.txt
# 判断计的数是否大于10
if [ $nu2 -gt 10 ]
then
# 是的话就发送一个告警邮件说明告警持续10分钟了
python3 ../mail/mail.py $1 "trouble continue 10 min $2" "$3"
# 重新计数
echo "0" > /tmp/$log.txt
fi
fi
八.运行测试告警系统
想要正常的运行这个告警系统你需要写一个任务计划,每分钟执行一次 main.sh 主脚本:
使用crontab命令来添加任务计划
[root@localhost mon]# crontab -e
* * * * * cd /usr/local/sbin/mon/bin; bash main.sh
不过,我这里由于只是做实验就不写以上这个任务计划了,直接手动运行,方便一会进行测试。在这之前需要修改一下配置文件,将to_mon_502改为0,因为本实验环境中并没有502.sh脚本里定义的站点目录,所以打开这个监控项的话会报错,然后还需要注释掉 main.sh 主脚本中的写入日志那句代码:
[root@localhost mon]# vi conf/mon.conf
# 改为0
to_mon_502=0
[root@localhost mon]# vi bin/main.sh
# 注释这一句代码
# exec 1>>../log/mon.log 2>>../log/err.log
完成以上操作后,切换到bin目录,执行main.sh主脚本:
[root@localhost mon]# cd bin
[root@localhost bin]# sh main.sh
2024-11-22 15:52:22 load average
15:52:22 load is 0
运行结果如上,没有出现报错信息,代表 load.sh 能够被正常执行。
以上已经验证load.sh可以正常被执行了,接下来我们再来测试一下能否正常发送邮件,首先修改一下load.sh中的判断条件,修改成小于10,因为要故意让它报警:
[root@localhost mon]# vi shares/load.sh
将if [ $load -gt 10 ] && [ $send -eq "1" ]改为if [ $load -lt 10 ] && [ $send -eq "1" ]
然后到bin目录下执行11次主脚本,因为我没有定义任务计划,所以需要模拟一分钟执行一次的情况,执行到第11次的时候会停顿一下,这是因为在发送邮件中:
可以看到提示邮件发送成功,然后我们去邮箱中查看可以看到邮件能够正常收到。
至此告警系统部署成功。
标签:load,Shell,log,系统,sh,mon,告警,日志 From: https://blog.csdn.net/2402_85534286/article/details/143976848