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 測試效果
可以手動觸發一個報警測試效果,手機上就可以收到帶圖的報警了,點擊消息之后的頁面也可以看到歷史的圖片
歡迎填加微信公眾號,大家共同交流,共同進步