在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 + '\n'
 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 + '\n'
 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 測試效果

可以手動觸發一個報警測試效果,手機上就可以收到帶圖的報警了,點擊消息之后的頁面也可以看到歷史的圖片

歡迎填加微信公眾號,大家共同交流,共同進步

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM