分享一个线上使用的自定义zabbix报警脚本,脚本思路大致如下:

    1.使用爬虫获取报警图片(前提是要获得报警的item)

    2.将图片与邮件内容整合

    3.发送邮件

    4.日志记录


脚本内容如下:

#!/usr/bin/python
#coding:utf-8

import sys,time,re,os,glob
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import urllib,urllib2,cookielib
import zlib

mail_host = '************'            # 邮件发送方相关信息
mail_user = '************'
mail_pass = '************'
mail_postfix = '************'

zabbix_user = "********"            # zabbix-web相关信息
zabbix_pass = "********"
url = "http://***********/"
alartscript_path="/**********/alertscripts/"        # 邮件脚本及日志位置
line = "ItemID"

me = "zabbix"+'<'+mail_user+'>'

######### 利用爬虫获取图片,保证cookie的可用性
def get_graph(itemID):
        login_url = url + "index.php"
        post_value = {"request":"",
                        "name":zabbix_user,
                        "password":zabbix_pass,
                        "autologin":"1",                #注意这个是否记住密码的选项,将造成生成的cookie长度不一样,短的能查看到图但没有数据
                        "enter":"Sign in"
                }
        post_data = urllib.urlencode(post_value)
        headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0",
                   "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                   "Accept-Encoding":"gzip, deflate",
                   "Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
                   "Connection":"Keep-Alive",
                   "Host":"**************",
                   "Referer":login_url,
                   ###########这个cookie很重要,要求当前cookie正在浏览器上正常使用,才能顺利取图
                   "Cookie":"******** zbx_sessionid=*********"
                }
        request = urllib2.Request(login_url,post_data,headers)
        cj = cookielib.CookieJar()
        opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
        urllib2.install_opener(opener)
        
        result = opener.open(request)
        print result.info()                                              #查看下内容信息,如果是gzip要解压写入文件
        result_html = zlib.decompress(result.read(), 16+zlib.MAX_WBITS)
        
        global graph_url                            # 构建用于访问图片的URL
        graph_url = url+"chart.php"+"?itemids="+str(itemID)
        graph_data = urllib2.urlopen(graph_url)
        print graph_data.info()#.get('Content-Encoding')
        #graph_html = zlib.decompress(graph_data.read(), 16+zlib.MAX_WBITS)
        print graph_data.info().get('Content-Type')
        image_data = graph_data.read()
        if graph_data.info().get('Content-Type') == "image/png":
                image_file = open('last_%s.pnj'%itemID,'wb')
                image_file.write(image_data)
                image_file.close()
        else:
                trigged = open('zabbix.png','rb')            # 如果获取图片data失败,打开一张事先准备好的图,这里使用的是zabbix的logo,在邮件中很直接的反应出获取图片失败
                image_data = trigged.read()
                trigged.close()
        print "Graph_URL:",graph_url
        return image_data
        
def mail_con(txtData,imageData):                    # 重写邮件内容(添加图片)
        msg = MIMEMultipart('related')
        msg['Subject'] = subject
        msg['From'] = me
        msg['to'] = receiver
        con_txt = MIMEText(txtData,_subtype='html',_charset='utf-8')
        msg.attach(con_txt)
        con_img = MIMEImage(imageData)
        con_img.add_header('Content-ID','digglife')        # 将要发送的图片嵌入到邮件头部,重写邮件内容
        msg.attach(con_img)
        return msg.as_string()
        
def send_mail(receiver,subject,contents):                # 邮件发送,并将结果记录
        logfile = open('alarm_mail.log','a')
        try:
                s = smtplib.SMTP()
                s.connect(mail_host)
                s.login(mail_user,mail_pass)
                s.sendmail(me,receiver,contents)
                s.close()
                log = time.ctime() + "\tOK\t" + subject +"\t"+ receiver + "\n"
        except Exception,e:
                log = time.ctime() + "\tFail\t" + subject +"\t"+ receiver + "\n"
        logfile.write("\n"+"\t"+graph_url+"\n")
        logfile.write(log)
        logfile.close()
        
if __name__ == "__main__":
        cur_pwd = os.getcwd()
        print cur_pwd
        os.chdir(alartscript_path)                # zabbix-server工作的路径为/,在这里切换邮件脚本路径,可以写入日志和图片处理,减少出错
        
        old_pnjs = glob.glob('last_*.pnj')
        for old_file in old_pnjs:
                os.remove(old_file)
        receiver = sys.argv[1]
        subject = sys.argv[2]
        src_mail_con = sys.argv[3]
        try:
                ItemID = re.match(r'.*ItemID:(\d+)[^\d]+.*',src_mail_con.replace('\n',''),re.S).group(1)        # 利用正则从邮件内容中获取itemID
        except:
                ItemID = 0000                # item为0000的是一张空图,减少异常情况
        print "ItemID:",ItemID
        
        ImageData = get_graph(ItemID)
        MailCon = mail_con(src_mail_con,ImageData)
        send_mail(receiver,subject,MailCon)

脚本中‘********’部分出于个人信息安全进行隐藏,读者可根据具体环境修改(发件箱信息,zabbix-web登陆信息及cookie)


脚本首先要获得报警itemID,以及邮件内容放置图片信息,因此还要自定义报警邮件内容,如下:

 邮件内容:  

    <body>
    故障通知<br/>
    触发器: {TRIGGER.NAME}<br/>
    主机名:{HOST.NAME}({IPADDRESS})<br/>
    状态: {TRIGGER.STATUS}<br/>
    告警级别: {TRIGGER.SEVERITY}<br/>
    URL: {TRIGGER.URL}<br/>
    <br/>
    告警项目:<br/>
    <br/>
    {ITEM.NAME1} ({HOST.NAME1}:{ITEM.KEY1}): {ITEM.VALUE1}<br/>
    <br/>
    <div style="line-height:1.7;color:#000000;font-size:14px;font-family:Arial">
    <img src="cid:digglife" orgwidth="1016" orgheight="376" data-image="1" style="width: 780px; height: 288px;">
    </div>
    ItemID:{ITEM.ID}<br/>
    EventID: {EVENT.ID}<br/>
    告警时间:{EVENT.DATE} {EVENT.TIME} <br/>
    <br/>
    详细信息:<a href="http://*******/history.php?action=showgraph&itemids[]={ITEM.ID}" target="_blank">登录查看</a><br/>
    </body>


效果如下

    QQ邮箱接收邮件,显示内容:

wKiom1dgvSuS1qFvAAF8YigS1no396.png-wh_50

    日志记录:

wKiom1dgwZ2yT6UNAAARijI_uhU972.png