zoukankan      html  css  js  c++  java
  • 在zabbix中实现发送带有图片的邮件和微信告警

    1 python实现在4.2版本zabbix发送带有图片的报警邮件

    我们通常收到的报警,都是文字,是把动作中的消息内容当成了正文参数传给脚本,然后邮件或者微信进行接收,往往只能看到当前值,无法直观的获取到历史当天该监控项的运行曲线图,因此根据此需求,使用python编写脚本来分别对邮件告警和微信告警,进行升级,报警内容中加入了当天的历史趋势图,功夫不负有心人,已成功解锁,并实践成功,因此分享出来供大家参考,另外得非常感谢脚本编写中刚哥大神和王二基友给予的帮助

    1.1 实现思路

    • 首先报警信息里第一行要有itemid,这是前提,根据信息里传入的参数使用正则匹配到itemid

    • 使用脚本创建一个zabbix会话,来根据itemid来获取图片,并将获取到的图片保存到本地

    • 将传入的参数信息的text字段转换成HTML格式,然后将HTML格式的信息和图片作为邮件进行发送

    1.2 准备环境

    • 脚本是使用python脚本,运行环境为python 2.7.5

    • 依赖库:

      requests

    1.3 脚本实现

      1 [root@5804703917ad zabbix]# cd /usr/lib/zabbix/alertscripts/  #进入zabbix默认的脚本路径
      2 [root@5804703917ad alertscripts]# mkdir graph #创建一个存放图片的文件夹
      3 [root@5804703917ad alertscripts]# chmod 777 graph #给文件夹赋予权限
      4 [root@5804703917ad alertscripts]# vim zabbix_email_pic.py #编写实现脚本
      5 #!/usr/bin/python
      6 #coding=utf-8
      7 from email.mime.text import MIMEText
      8 from email.mime.multipart import MIMEMultipart
      9 from email.mime.image import MIMEImage
     10 import smtplib,sys,os,time,re,requests
     11 from smtplib import SMTP
     12  13 user='Admin'    #定义zabbix用户名
     14 password='zabbix'    #定义zabbix用户密码
     15 graph_path='/usr/lib/zabbix/alertscripts/graph'   #定义图片存储路径
     16 graph_url='http://192.168.73.133/chart.php'     #定义图表的url
     17 loginurl="http://192.168.73.133/index.php"          #定义登录的url
     18 host='192.168.73.133'
     19 to_email=sys.argv[1]    #传入的第一个参数为收件人邮箱
     20 subject=sys.argv[2]  #传入的第二个参数为邮件主题
     21 subject=subject.decode('utf-8')
     22 smtp_host = 'smtp.163.com'  #定义smtp主机地址
     23 from_email = 'xxxx@163.com.cn'     #定义发件人地址
     24 mail_pass = 'xxx'       #发件人邮箱校验码
     25  26 def get_itemid():
     27     #获取报警的itemid
     28     itemid=re.search(r'监控ID:(d+)',sys.argv[3]).group(1)
     29     return itemid
     30  31 def get_graph(itemid):
     32     #获取报警的图表并保存
     33     session=requests.Session()   #创建一个session会话
     34     try:
     35         loginheaders={
     36         "Host":host,
     37         "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
     38         }
     39         #定义请求消息头
     40  41         payload = {
     42         "name":user,
     43         "password":password,
     44         "autologin":"1",
     45         "enter":"Sign in",
     46         }
     47         #定义传入的data
     48         login=session.post(url=loginurl,headers=loginheaders,data=payload)
     49         #进行登录
     50         graph_params={
     51             "from" :"now-10m",
     52             "to" : "now",
     53             "itemids" : itemid,
     54             "width" : "400",
     55         }
     56         #定义获取图片的参数
     57         graph_req=session.get(url=graph_url,params=graph_params)
     58         #发送get请求获取图片数据
     59         time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime())
     60         graph_name='baojing_'+time_tag+'.png'
     61         #用报警时间来作为图片名进行保存
     62         graph_name = os.path.join(graph_path, graph_name)
     63         #使用绝对路径保存图片
     64         with open(graph_name,'wb') as f:
     65             f.write(graph_req.content)
     66             #将获取到的图片数据写入到文件中去
     67         return graph_name
     68  69     except Exception as e:
     70         print(e)
     71         return False
     72 def text_to_html(text):
     73     #将邮件内容text字段转换成HTML格式
     74     d=text.splitlines()
     75     #将邮件内容以每行作为一个列表元素存储在列表中
     76     html_text=''
     77     for i in d:
     78         i='' + i + '<br>'
     79         html_text+=i + '
    '
     80     #为列表的每个元素后加上html的换行标签
     81     return html_text
     82  83 def send_mail(graph_name):
     84     #将html和图片封装成邮件进行发送
     85     msg = MIMEMultipart('related')  #创建内嵌资源的实例
     86  87     with open(graph_name,'rb') as f:
     88         #读取图片文件
     89         graph=MIMEImage(f.read())  #读取图片赋值一个图片对象
     90     graph.add_header('Content-ID','imgid1')  #为图片对象添加标题字段和值
     91     text=text_to_html(sys.argv[3])
     92     html="""
     93     <html>
     94       <body>
     95       %s  <br><img src="cid:imgid1">
     96       </body>
     97     </html>
     98     """ % text
     99     html=MIMEText(html,'html','utf-8')  #创建HTML格式的邮件体
    100     msg.attach(html)   #使用attach方法将HTML添加到msg实例中
    101     msg.attach(graph)  #使用attach方法将图片添加到msg实例中
    102     msg['Subject'] = subject
    103     msg['From'] = from_email
    104     try:
    105         server=SMTP(smtp_host,"587")   #创建一个smtp对象
    106         server.starttls()    #启用安全传输模式
    107         server.login(from_email,mail_pass)  #邮箱账号登录
    108         server.sendmail(from_email,to_email,msg.as_string())  #发送邮件
    109         server.quit()   #断开smtp连接
    110     except smtplib.SMTPException as a:
    111         print(a)
    112 113 def run():
    114     itemid=get_itemid()
    115     graph_name=get_graph(itemid)
    116     send_mail(graph_name)
    117 118 if __name__ =='__main__':
    119     run()

    1.4 定义报警媒介类型

    • 打开zabbix监控web,在管理菜单中选择报警媒介类型,创建媒体类型,选择脚本,填写刚才编写的邮件带图脚本名称zabbix_email_pic.py,脚本参数,最后添加

    • 打开管理中的用户,点击需要设置邮件告警的用户,然后在报警媒介中添加报警媒介,在弹框中选择刚才定义的类型,然后填写想要发送的邮箱地址,最后添加

      1.5 定义告警动作

    • 点击配置菜单中的动作,创建动作,然后根据图片进行填写

    操作
    默认标题 Zabbix告警:服务器:{HOSTNAME}发生: {TRIGGER.NAME}故障!
    监控ID:{ITEM.ID}
    告警主机:{HOST.NAME}
    告警主机:{HOST.IP}
    告警时间:{EVENT.DATE} {EVENT.TIME}
    告警等级:{TRIGGER.SEVERITY}
    告警信息: {TRIGGER.NAME}
    告警项目:{TRIGGER.KEY}
    问题详情:{ITEM.NAME}:{ITEM.VALUE}
    当前状态:{TRIGGER.STATUS}:{ITEM.VALUE}
    事件ID:{EVENT.ID}
    恢复操作
    Zabbix告警:服务器:{HOST.NAME}发生: {TRIGGER.NAME}已恢复!
    监控ID:{ITEM.ID}
    告警主机:{HOST.NAME}
    告警主机:{HOST.IP}
    告警时间:{EVENT.DATE} {EVENT.TIME}
    告警等级:{TRIGGER.SEVERITY}
    告警信息: {TRIGGER.NAME}
    告警项目:{TRIGGER.KEY}


    1.6 最终效果

    可以手动触发一个报警测试效果

    2 python实现在4.2版本zabbix发送带有图片的微信告警

    2.1 实现思路

    • 首先创建企业公众号获取agentId,secret和部门id

    • 然后根据报警信息获取itemid,使用正则匹配到itemid

    • 使用脚本创建一个zabbix会话,来根据itemid来获取图片,并将获取到的图片保存到本地

    • 调用企业微信api接口,把图片当成临时素材上传,返回一个media_id,给发送消息和图片调用使用,最后使用mpnews消息类型把图片和报警内容进行推送到微信上

      2.2 准备环境

    • 脚本是使用python脚本,运行环境为python 2.7.5

    • 依赖库提前安装:

      requests

    2.3 创建企业公众号获取agentid,secret

    这部分内容,可以查看前面不带图的文章有详细描述

    2.4 脚本实现

      1 [root@5804703917ad zabbix]# cd /usr/lib/zabbix/alertscripts/  #进入zabbix默认的脚本路径
      2 [root@5804703917ad alertscripts]# mkdir graph #创建一个存放图片的文件夹
      3 [root@5804703917ad alertscripts]# chmod 777 graph #给文件夹赋予权限
      4 [root@5804703917ad alertscripts]# vim zabbix_weixin_pic.py #编写实现脚本
      5 #!/usr/bin/python
      6 #coding=utf-8
      7 _author__ = 'zhangdongdong'
      8 import requests, json
      9 import urllib3
     10 import smtplib,sys,os,time,re,requests
     11 from email.mime.image import MIMEImage
     12 if sys.getdefaultencoding() != 'utf-8':
     13     reload(sys)
     14     sys.setdefaultencoding('utf-8')
     15 urllib3.disable_warnings()
     16 class WechatImage(object): # 根据企业微信api接口文档,定义一个类,使用mpnews类型,https://qydev.weixin.qq.com/wiki/index.php?title=%E6%B6%88%E6%81%AF%E7%B1%BB%E5%9E%8B%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F
     17  18     def get_token(self, corpid, secret): # 获取token
     19         url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
     20         data = {"corpid": corpid,
     21                 "corpsecret": secret}
     22         r = requests.get(url=url, params=data, verify=False)
     23         token = r.json()['access_token']
     24         return token
     25  26     def get_image_url(self, token, path): # 上传临时素材图片,然后返回media_id
     27         url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=image" % token
     28         data = {"media": open(path, 'rb')}
     29         r = requests.post(url=url, files=data)
     30         dict_data = r.json()
     31         return dict_data['media_id']
     32     def get_messages( self,subject,content,path): #定义mpnews类型中的参数字典
     33         data = ''
     34         messages = {}
     35         body = {}
     36         content_html=text_to_html(content)
     37         token = self.get_token(corpid, secret)
     38         image = self.get_image_url(token, path)
     39         content_html += "<br/> <img src='https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s'>" % (token, image)
     40         body["title"] = subject
     41         body['digest'] = content
     42         body['content'] = content_html
     43         body['thumb_media_id'] = image
     44         data = []
     45         data.append(body)
     46         messages['articles'] = data
     47         return messages
     48     def send_news_message(self, corpid, secret,to_user, agentid,path): #定义发送mpnews类型的数据
     49         token = self.get_token(corpid, secret)
     50         messages = self.get_messages( subject, content,path)
     51         url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s" % token
     52         data = {"toparty": to_user,                                 # 企业号中的用户帐号
     53                 "agentid": agentid,                             # 企业号中的应用id
     54                 "msgtype": "mpnews",
     55                 "mpnews": messages,
     56                 "safe": "0"}
     57         headers = {'content-type': 'application/json'}
     58         data_dict = json.dumps(data, ensure_ascii=False).encode('utf-8')
     59         r = requests.post(url=url, headers=headers, data=data_dict)
     60         return r.text
     61 def text_to_html(text): #将邮件内容text字段转换成HTML格式
     62     d=text.splitlines()
     63     #将邮件内容以每行作为一个列表元素存储在列表中
     64     html_text=''
     65     for i in d:
     66         i='' + i + '<br>'
     67         html_text+=i + '
    '
     68     #为列表的每个元素后加上html的换行标签
     69     return html_text
     70 def get_itemid():
     71     #获取报警的itemid
     72     itemid=re.search(r'监控ID:(d+)',sys.argv[3]).group(1)
     73     return itemid
     74 def get_graph(itemid):
     75     #获取报警的图表并保存
     76     session=requests.Session()   #创建一个session会话
     77     try:
     78         loginheaders={
     79         "Host":host,
     80         "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
     81         }
     82         #定义请求消息头
     83  84         payload = {
     85         "name":user,
     86         "password":password,
     87         "autologin":"1",
     88         "enter":"Sign in",
     89         }
     90         #定义传入的data
     91         login=session.post(url=loginurl,headers=loginheaders,data=payload)
     92         #进行登录
     93         graph_params={
     94             "from" :"now-10m",
     95             "to" : "now",
     96             "itemids" : itemid,
     97             "width" : "290", #图片的高宽参数可以自行调整
     98             "height" : "40",
     99         }
    100         #定义获取图片的参数
    101         graph_req=session.get(url=graph_url,params=graph_params)
    102         #发送get请求获取图片数据
    103         time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime())
    104         graph_name='baojing_'+time_tag+'.png'
    105         #用报警时间来作为图片名进行保存
    106         graph_name = os.path.join(graph_path, graph_name)
    107         #使用绝对路径保存图片
    108         with open(graph_name,'wb') as f:
    109             f.write(graph_req.content)
    110             #将获取到的图片数据写入到文件中去
    111         return graph_name
    112     except Exception as e:
    113         print(e)
    114         return False
    115 if __name__ == '__main__':
    116     user='Admin'    #定义zabbix用户名
    117     password='zabbix'    #定义zabbix用户i密
    118     graph_path='/usr/lib/zabbix/alertscripts/graph/'   #定义图片存储路径,图片需要定时清理
    119     graph_url='http://192.168.73.133/chart.php'     #定义图表的url
    120     loginurl="http://192.168.73.133/index.php"          #定义登录的url
    121     host='192.168.73.133'
    122     itemid=get_itemid()
    123     path =get_graph(itemid)
    124     to_user = str(sys.argv[1]) 
    125     subject = str(sys.argv[2]) 
    126     content = str(sys.argv[3])
    127     corpid= "xxxxx"
    128     secret = "xxxxxxx"
    129     agentid = "1000002"
    130     wechat_img = WechatImage()
    131     wechat_img.send_news_message(corpid, secret,to_user, agentid, path)
     
    • 打开zabbix监控web,在管理菜单中选择报警媒介类型,创建媒体类型,选择脚本,填写刚才编写的微信带图脚本名称zabbix_weixin_pic.py,脚本参数,最后添加

    • 打开管理中的用户,点击需要设置邮件告警的用户,然后在报警媒介中添加报警媒介,在弹框中选择刚才定义的类型,然后填写企业微信中创建的部门id,最后添加

      2.6 定义告警动作

    • 点击配置菜单中的动作,创建动作,然后根据图片进行填写

    操作
    默认标题 Zabbix告警:服务器:{HOSTNAME}发生: {TRIGGER.NAME}故障!
    监控ID:{ITEM.ID}
    告警主机:{HOST.NAME}
    告警主机:{HOST.IP}
    告警时间:{EVENT.DATE} {EVENT.TIME}
    告警等级:{TRIGGER.SEVERITY}
    告警信息: {TRIGGER.NAME}
    告警项目:{TRIGGER.KEY}
    问题详情:{ITEM.NAME}:{ITEM.VALUE}
    当前状态:{TRIGGER.STATUS}:{ITEM.VALUE}
    事件ID:{EVENT.ID}
    恢复操作
    Zabbix告警:服务器:{HOST.NAME}发生: {TRIGGER.NAME}已恢复!
    监控ID:{ITEM.ID}
    告警主机:{HOST.NAME}
    告警主机:{HOST.IP}
    告警时间:{EVENT.DATE} {EVENT.TIME}
    告警等级:{TRIGGER.SEVERITY}
    告警信息: {TRIGGER.NAME}
    告警项目:{TRIGGER.KEY}
    问题详情:{ITEM.NAME}:{ITEM.VALUE}
    当前状态:{TRIGGER.STATUS}:{ITEM.VALUE}
    事件ID:{EVENT.ID}



    2.7 测试效果

    可以手动触发一个报警测试效果,手机上就可以收到带图的报警了,点击消息之后的页面也可以看到历史的图片

    欢迎填加微信公众号,大家共同交流,共同进步

  • 相关阅读:
    Ubuntu深度学习环境搭建 tensorflow+pytorch
    FineReport调用存储过程
    简单实现固定表格的上表头、左表头
    为什么vertical-align不起作用
    纪录我的iOS学习之路
    【原】使用Bmob作为iOS后台开发心得——云端代码添加其他User的Relation关系
    【原】使用Bmob作为iOS后台开发心得——查询关联关系(BmobRelation)
    【译】Unity3D Shader 新手教程(6/6) —— 更好的卡通Shader
    【译】Unity3D Shader 新手教程(5/6) —— Bumped Diffuse Shader
    【译】Unity3D Shader 新手教程(4/6) —— 卡通shader(入门版)
  • 原文地址:https://www.cnblogs.com/double-dong/p/11809961.html
Copyright © 2011-2022 走看看