去博客園找我!
alittlemc - 博客園
前言
近期在琢磨Zabbix郵箱報(bào)警的功能,但是網(wǎng)上的教程通常是4.0或5.0版本Zabbix,并使用Python2.7環(huán)境祭饭,運(yùn)行在新版本Zabbix6.0上有頗多問題,為此我基于原先教程修改基于Zabbix6.0并使用Python3+的解決方案。期間遇到不少坑脑又,特此分享。
Zabbix自帶報(bào)警
Zabbix是自帶的郵箱的報(bào)警功能有限,比如不能實(shí)現(xiàn)諸如郵件插入圖片的功能,而可以使用執(zhí)行腳本功能則可以調(diào)用本地程序撮抓,調(diào)用Python腳本從而實(shí)現(xiàn)許多如發(fā)送企業(yè)微信、釘釘使用的功能摇锋。
前端設(shè)置
報(bào)警媒介
在zabbix中保存腳本文件的目錄為/usr/lib/zabbix/alertscripts/
,目前4.0\5.0\6.0都通用丹拯,將shell腳本文件保存于此可以直接在報(bào)警媒介類型
調(diào)用。
參數(shù)需要傳遞給腳本荸恕,對于著Shell腳本中的$1
乖酬、$2
、$3
融求。
{ALERT.SENDTO} //發(fā)件人(對應(yīng)著用戶\報(bào)警媒介中配置的發(fā)件人)
{ALERT.SUBJECT} //主題(對應(yīng)著主題模版)
{ALERT.MESSAGE} //消息內(nèi)容(對應(yīng)著消息模版)
發(fā)件人
主題\消息內(nèi)容
報(bào)警媒介消息模版
在消息模版中咬像,添加問題發(fā)生
// 問題發(fā)生
// 主題
發(fā)生故障:服務(wù)器:{HOSTNAME}->{TRIGGER.NAME}警告!
// 消息
監(jiān)控ID:{ITEM.ID}
告警主機(jī):{HOST.NAME}
告警主機(jī):{HOST.IP}
告警時(shí)間:{EVENT.DATE} {EVENT.TIME}
告警等級:{TRIGGER.SEVERITY}
告警信息: {TRIGGER.NAME}
告警項(xiàng)目:{TRIGGER.KEY}
問題詳情:{ITEM.NAME}:{ITEM.VALUE}
當(dāng)前狀態(tài):{TRIGGER.STATUS}:{ITEM.VALUE}
事件ID:{EVENT.ID}
添加問題恢復(fù)
//問題恢復(fù)
// 主題
問題恢復(fù):服務(wù)器:{HOST.NAME}->{TRIGGER.NAME}已恢復(fù)!
// 消息
監(jiān)控ID:{ITEM.ID}
告警主機(jī):{HOST.NAME}
告警主機(jī):{HOST.IP}
告警時(shí)間:{EVENT.DATE} {EVENT.TIME}
告警等級:{TRIGGER.SEVERITY}
告警信息: {TRIGGER.NAME}
告警項(xiàng)目:{TRIGGER.KEY}
問題詳情:{ITEM.NAME}:{ITEM.VALUE}
當(dāng)前狀態(tài):{TRIGGER.STATUS}:{ITEM.VALUE}
事件ID:{EVENT.ID}
設(shè)置用戶報(bào)警媒介
在管理\用戶<用戶名>\報(bào)警媒介
如果有多個(gè)收件人,用,
分割,我在python中做了定義
設(shè)置動(dòng)作
要想要腳本觸發(fā)問題后執(zhí)行還需要設(shè)置
腳本實(shí)現(xiàn)
涉及到兩個(gè)腳本
Shell腳本
/usr/lib/zabbix/alertscripts/sedmail.zabbix.sh
主要是用于實(shí)現(xiàn)連接Python腳本双肤,測試、刪除圖片
創(chuàng)建/usr/lib/zabbix/alertscripts/graph
Python腳本
主要是實(shí)現(xiàn)Zabbix中圖片的下載钮惠、郵件發(fā)送
Shell腳本
新版本的Zabbix6.0貌似不支持直接執(zhí)行Python腳本茅糜,為此我使用一個(gè)shell腳本作為中轉(zhuǎn),且可實(shí)現(xiàn)簡單的測試素挽、刪除圖片文件蔑赘。
/usr/lib/zabbix/alertscripts/sedmail.zabbix.sh
#!/bin/bash
cd `dirname $0`
echo "{ALERT.SENDTO} = $1" > debug.txt
echo "{ALERT.SUBJECT} = $2" >> debug.txt
echo "{ALERT.MESSAGE} = $3" >> debug.txt
python3 sedmail.zabbix.py "$1" "$2" "$3" >> debug.txt
echo "shell success" >> debug.txt
find graph -type f -name "*.png" | xargs rm
Python腳本
主要是實(shí)現(xiàn)Zabbix中圖片的下載、郵件發(fā)送预明,本Python腳本使用Python3環(huán)境缩赛,如果你需
腳本過程
- 解析傳遞過來的
主題{ALERT.SENDTO}
、主題{ALERT.SUBJECT}
撰糠、消息{ALERT.MESSAGE}
消息中的監(jiān)控ID:
后的數(shù)字酥馍,即itemid,此項(xiàng)極為重要
itemid=re.search(r'監(jiān)控ID:(\d+)',sys.argv[3]).group(1)
# 如果你改了消息模版記得修改一下search匹配規(guī)則
- 登錄Zabbix:使用Post登錄http://zabbix:8080/index.php
"name":user, # 用戶
"password":password, # 密碼
"autologin":"1", # 30天內(nèi)自動(dòng)登錄
"enter":"登錄", # 請注意這個(gè)對應(yīng)你語言,如果是英文為login on,可以抓包看看
- 故障的統(tǒng)計(jì)圖下載阅酪,對應(yīng)著先前的
itemid
參數(shù)旨袒,可以使用get請求http://zabbix:8080/chart.php
后帶的參數(shù)
"from" :"now-30m",
"to" : "now",
"itemids[0]" : itemid,# 請注意,Zabbix6.0中是itemid[0],在更老的4.0\5.0使用的itemid
"width" : "300",
#對應(yīng)的url,以itemid[0]=79672為例
http://zabbix:8080/chart.php?from=now-30m&to=now&itemids%5B0%5D=79672&width=300
注意需要在登錄的前提下,并且login的headers消息頭一致术辐,不然對提示錯(cuò)誤
文件會(huì)保存在graph_path='/usr/lib/zabbix/alertscripts/graph'
如果沒有此文件夾需要?jiǎng)?chuàng)建
完整腳本
/usr/lib/zabbix/alertscripts/sedmail.zabbix.py
#!/usr/bin/python3
#coding=utf-8
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import smtplib,sys,os,time,re,requests,logging
from smtplib import SMTP
user='Admin' #定義zabbix用戶名
password='password' #定義zabbix用戶密碼
graph_path='/usr/lib/zabbix/alertscripts/graph' #定義圖片存儲路徑
graph_url='http://127.0.0.1:8080/chart.php' #定義圖表的url
loginurl="http://127.0.0.1:8080/index.php" #定義登錄的url
host='127.0.0.1'
to_email=sys.argv[1].split(',') #傳入的第一個(gè)參數(shù)為收件人郵箱
subject=sys.argv[2] #傳入的第二個(gè)參數(shù)為郵件主題
subject=subject.encode('utf-8').decode('utf-8')
smtp_host = 'smtp.xxx.net' #定義smtp主機(jī)地址
from_email = 'alittlemc@xxx.com' #定義發(fā)件人地址
mail_pass = 'xxx' #發(fā)件人郵箱校驗(yàn)碼\密碼
def get_itemid():
#獲取報(bào)警的itemid
itemid=re.search(r'監(jiān)控ID:(\d+)',sys.argv[3]).group(1)
return itemid
def get_graph(itemid):
#獲取報(bào)警的圖表并保存
session=requests.Session() #創(chuàng)建一個(gè)session會(huì)話
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":"登錄",
}
#定義傳入的data
login=session.post(url=loginurl,headers=loginheaders,data=payload)
# print(login.text)
#進(jìn)行登錄
graph_params={
"from" :"now-30m",
"to" : "now",
"itemids[0]" : itemid,
"width" : "300",
}
# print(itemid)
# http://zabbix:8080/chart.php?from=now-1m&to=now&itemids%5B0%5D=79672
#定義獲取圖片的參數(shù)
graph_req=session.get(url=graph_url,params=graph_params,headers=loginheaders)
#發(fā)送get請求獲取圖片數(shù)據(jù)
time_tag=time.strftime("%Y%m%d%H%M%S", time.localtime())
graph_name='baojing_'+time_tag+'.png'
#用報(bào)警時(shí)間來作為圖片名進(jìn)行保存
graph_name = os.path.join(graph_path, graph_name)
#使用絕對路徑保存圖片
with open(graph_name,'wb') as f:
f.write(graph_req.content)
#將獲取到的圖片數(shù)據(jù)寫入到文件中去
return graph_name
except Exception as e:
# print(e)
return False
def text_to_html(text):
#將郵件內(nèi)容text字段轉(zhuǎn)換成HTML格式
d=text.splitlines()
#將郵件內(nèi)容以每行作為一個(gè)列表元素存儲在列表中
html_text=''
for i in d:
i='' + i + '<br>'
html_text+=i + '\n'
#為列表的每個(gè)元素后加上html的換行標(biāo)簽
return html_text
def send_mail(graph_name):
#將html和圖片封裝成郵件進(jìn)行發(fā)送
msg = MIMEMultipart('related') #創(chuàng)建內(nèi)嵌資源的實(shí)例
with open(graph_name,'rb') as f:
#讀取圖片文件
graph=MIMEImage(f.read()) #讀取圖片賦值一個(gè)圖片對象
graph.add_header('Content-ID','imgid1') #為圖片對象添加標(biāo)題字段和值
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') #創(chuàng)建HTML格式的郵件體
msg.attach(html) #使用attach方法將HTML添加到msg實(shí)例中
msg.attach(graph) #使用attach方法將圖片添加到msg實(shí)例中
msg['Subject'] = subject
msg['From'] = from_email
try:
server=SMTP(smtp_host,"587") #創(chuàng)建一個(gè)smtp對象
server.starttls() #啟用安全傳輸模式
server.login(from_email,mail_pass) #郵箱賬號登錄
for x in to_email:
server.sendmail(from_email,x,msg.as_string()) #發(fā)送郵件
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()
print('success',sys.argv[1],sys.argv[2],sys.argv[3])
測試
可以直接使用報(bào)警媒介的測試功能砚尽,對應(yīng)的傳輸主題{ALERT.SENDTO}
、主題{ALERT.SUBJECT}
辉词、消息{ALERT.MESSAGE}
消息