在zabbix中實現發送帶有圖片的郵件和微信告警

  • 2019 年 11 月 10 日
  • 筆記

夫天地者,萬物之逆旅也;光陰者,百代之過客也。 李白《春夜宴從弟桃花園序》


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 腳本實現

[root@5804703917ad zabbix]# cd /usr/lib/zabbix/alertscripts/  #進入zabbix默認的腳本路徑[root@5804703917ad alertscripts]# mkdir graph #創建一個存放圖片的文件夾[root@5804703917ad alertscripts]# chmod 777 graph #給文件夾賦予許可權[root@5804703917ad alertscripts]# vim zabbix_email_pic.py #編寫實現腳本#!/usr/bin/python#coding=utf-8from email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.mime.image import MIMEImageimport smtplib,sys,os,time,re,requestsfrom smtplib import SMTP  user='Admin'    #定義zabbix用戶名password='zabbix'    #定義zabbix用戶密碼graph_path='/usr/lib/zabbix/alertscripts/graph'   #定義圖片存儲路徑graph_url='http://192.168.73.133/chart.php'     #定義圖表的urlloginurl="http://192.168.73.133/index.php"          #定義登錄的urlhost='192.168.73.133'to_email=sys.argv[1]    #傳入的第一個參數為收件人郵箱subject=sys.argv[2]  #傳入的第二個參數為郵件主題subject=subject.decode('utf-8')smtp_host = 'smtp.163.com'  #定義smtp主機地址from_email = '[email protected]'     #定義發件人地址mail_pass = 'xxx'       #發件人郵箱校驗碼  def get_itemid():    #獲取報警的itemid    itemid=re.search(r'監控ID:(d+)',sys.argv[3]).group(1)    return itemid  def get_graph(itemid):    #獲取報警的圖表並保存    session=requests.Session()   #創建一個session會話    try:        loginheaders={        "Host":host,        "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"        }        #定義請求消息頭          payload = {        "name":user,        "password":password,        "autologin":"1",        "enter":"Sign in",        }        #定義傳入的data        login=session.post(url=loginurl,headers=loginheaders,data=payload)        #進行登錄        graph_params={            "from" :"now-10m",            "to" : "now",            "itemids" : itemid,            "width" : "400",        }        #定義獲取圖片的參數        graph_req=session.get(url=graph_url,params=graph_params)        #發送get請求獲取圖片數據        time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime())        graph_name='baojing_'+time_tag+'.png'        #用報警時間來作為圖片名進行保存        graph_name = os.path.join(graph_path, graph_name)        #使用絕對路徑保存圖片        with open(graph_name,'wb') as f:            f.write(graph_req.content)            #將獲取到的圖片數據寫入到文件中去        return graph_name      except Exception as e:        print(e)        return Falsedef text_to_html(text):    #將郵件內容text欄位轉換成HTML格式    d=text.splitlines()    #將郵件內容以每行作為一個列表元素存儲在列表中    html_text=''    for i in d:        i='' + i + '<br>'        html_text+=i + 'n'    #為列表的每個元素後加上html的換行標籤    return html_text  def send_mail(graph_name):    #將html和圖片封裝成郵件進行發送    msg = MIMEMultipart('related')  #創建內嵌資源的實例      with open(graph_name,'rb') as f:        #讀取圖片文件        graph=MIMEImage(f.read())  #讀取圖片賦值一個圖片對象    graph.add_header('Content-ID','imgid1')  #為圖片對象添加標題欄位和值    text=text_to_html(sys.argv[3])    html="""    <html>      <body>      %s  <br><img src="cid:imgid1">      </body>    </html>    """ % text    html=MIMEText(html,'html','utf-8')  #創建HTML格式的郵件體    msg.attach(html)   #使用attach方法將HTML添加到msg實例中    msg.attach(graph)  #使用attach方法將圖片添加到msg實例中    msg['Subject'] = subject    msg['From'] = from_email    try:        server=SMTP(smtp_host,"587")   #創建一個smtp對象        server.starttls()    #啟用安全傳輸模式        server.login(from_email,mail_pass)  #郵箱帳號登錄        server.sendmail(from_email,to_email,msg.as_string())  #發送郵件        server.quit()   #斷開smtp連接    except smtplib.SMTPException as a:        print(a)  def run():    itemid=get_itemid()    graph_name=get_graph(itemid)    send_mail(graph_name)  if __name__ =='__main__':    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}問題詳情:{ITEM.NAME}:{ITEM.VALUE}當前狀態:{TRIGGER.STATUS}:{ITEM.VALUE}事件ID:{EVENT.ID}

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 腳本實現

[root@5804703917ad zabbix]# cd /usr/lib/zabbix/alertscripts/  #進入zabbix默認的腳本路徑[root@5804703917ad alertscripts]# mkdir graph #創建一個存放圖片的文件夾[root@5804703917ad alertscripts]# chmod 777 graph #給文件夾賦予許可權[root@5804703917ad alertscripts]# vim zabbix_weixin_pic.py #編寫實現腳本#!/usr/bin/python#coding=utf-8_author__ = 'zhangdongdong'import requests, jsonimport urllib3import smtplib,sys,os,time,re,requestsfrom email.mime.image import MIMEImageif sys.getdefaultencoding() != 'utf-8':    reload(sys)    sys.setdefaultencoding('utf-8')urllib3.disable_warnings()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      def get_token(self, corpid, secret): # 獲取token        url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"        data = {"corpid": corpid,                "corpsecret": secret}        r = requests.get(url=url, params=data, verify=False)        token = r.json()['access_token']        return token      def get_image_url(self, token, path): # 上傳臨時素材圖片,然後返回media_id        url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=image" % token        data = {"media": open(path, 'rb')}        r = requests.post(url=url, files=data)        dict_data = r.json()        return dict_data['media_id']    def get_messages( self,subject,content,path): #定義mpnews類型中的參數字典        data = ''        messages = {}        body = {}        content_html=text_to_html(content)        token = self.get_token(corpid, secret)        image = self.get_image_url(token, path)        content_html += "<br/> <img src='https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s'>" % (token, image)        body["title"] = subject        body['digest'] = content        body['content'] = content_html        body['thumb_media_id'] = image        data = []        data.append(body)        messages['articles'] = data        return messages    def send_news_message(self, corpid, secret,to_user, agentid,path): #定義發送mpnews類型的數據        token = self.get_token(corpid, secret)        messages = self.get_messages( subject, content,path)        url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s" % token        data = {"toparty": to_user,                                 # 企業號中的用戶帳號                "agentid": agentid,                             # 企業號中的應用id                "msgtype": "mpnews",                "mpnews": messages,                "safe": "0"}        headers = {'content-type': 'application/json'}        data_dict = json.dumps(data, ensure_ascii=False).encode('utf-8')        r = requests.post(url=url, headers=headers, data=data_dict)        return r.textdef text_to_html(text): #將郵件內容text欄位轉換成HTML格式    d=text.splitlines()    #將郵件內容以每行作為一個列表元素存儲在列表中    html_text=''    for i in d:        i='' + i + '<br>'        html_text+=i + 'n'    #為列表的每個元素後加上html的換行標籤    return html_textdef get_itemid():    #獲取報警的itemid    itemid=re.search(r'監控ID:(d+)',sys.argv[3]).group(1)    return itemiddef get_graph(itemid):    #獲取報警的圖表並保存    session=requests.Session()   #創建一個session會話    try:        loginheaders={        "Host":host,        "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"        }        #定義請求消息頭          payload = {        "name":user,        "password":password,        "autologin":"1",        "enter":"Sign in",        }        #定義傳入的data        login=session.post(url=loginurl,headers=loginheaders,data=payload)        #進行登錄        graph_params={            "from" :"now-10m",            "to" : "now",            "itemids" : itemid,            "width" : "290", #圖片的高寬參數可以自行調整            "height" : "40",        }        #定義獲取圖片的參數        graph_req=session.get(url=graph_url,params=graph_params)        #發送get請求獲取圖片數據        time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime())        graph_name='baojing_'+time_tag+'.png'        #用報警時間來作為圖片名進行保存        graph_name = os.path.join(graph_path, graph_name)        #使用絕對路徑保存圖片        with open(graph_name,'wb') as f:            f.write(graph_req.content)            #將獲取到的圖片數據寫入到文件中去        return graph_name    except Exception as e:        print(e)        return Falseif __name__ == '__main__':    user='Admin'    #定義zabbix用戶名    password='zabbix'    #定義zabbix用戶i密    graph_path='/usr/lib/zabbix/alertscripts/graph/'   #定義圖片存儲路徑,圖片需要定時清理    graph_url='http://192.168.73.133/chart.php'     #定義圖表的url    loginurl="http://192.168.73.133/index.php"          #定義登錄的url    host='192.168.73.133'    itemid=get_itemid()    path =get_graph(itemid)    to_user = str(sys.argv[1])     subject = str(sys.argv[2])     content = str(sys.argv[3])    corpid= "xxxxx"    secret = "xxxxxxx"    agentid = "1000002"    wechat_img = WechatImage()    wechat_img.send_news_message(corpid, secret,to_user, agentid, path)

2.5 定義報警媒介類型

  • 打開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 測試效果

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