ZABBIX之旅(5.0版以上)
【背景说明】运维系统使用时Zabbix工具,需添加微信公众号、微信企业号进行异常数据提醒的消息推送功能。
【系统环境】
Linux系统、Python3、Pip
【应用工具】
Mac Pro ---- FinalShell
一、企业微信信息推送
为什么选用微信企业号?
因为微信企业号需要先在企业通信录新建该员工,该员工才能关注该企业号,这样就能实现告警信息的私密性。如果使用公众号,则只要所有关注了该公众号的人都能收到告警消息,容易造成信息泄露。而且员工数少于200人的企业号是不用钱的,也没有任何申请限制。
实现步骤
-
注册微信企业号
打开以下链接注册微信企业号:https://work.weixin.qq.com/wework_admin/register_wx?from=myhome选择没有营业执照继续注册(限员工数200人以下),如下图所示,如果是正规大企业使用,请正常注册。
填上企业名称即可注册完成,后面还需要指定企业号管理员,按步骤绑定好管理员微信即可。
- 在企业号上创建告警应用
该告警应用的角色如下:Zabbix_server ---------> 告警应用 --------> 运维人员微信号
在企业号上创建一个应用,如下图所示:
image填好相关资料,应用即可创建完成,如上图本文创建的应用叫Zabbix告警
企业号上的重要信息
这里重点提一下企业号里几点重要的信息,等会在脚本中会用到
-
corpid
企业号的ID号,获得地方如下图所示:
image应用的安全码和agentid,获得地方如下图所示:
至此,可获取到重要的参数 - 企业号应用信息:
crop_id、corp_secret、agent_id
Zabbix报警脚本
外部脚本存放路径(默认):
/usr/share/zabbix/alertscripts/
可修改外部脚本存放路径地址文件
vim /etc/zabbix/zabbix_server.conf
大概在第500行代码左右可以查看到。
python脚本代码如下(替换下面的‘xxxxx’部分)
#!/usr/bin python3
import requests
import json
import sys
# 企业号及应用相关信息
corp_id = 'xxxxxxx'
corp_secret = 'xxxxxxx'
agent_id = xxxxxxx
# 存放access_token文件路径
file_path = '/tmp/access_token.log'
def get_access_token_from_file():
try:
f = open(file_path,'r+')
this_access_token = f.read()
print('get success %s' % this_access_token)
f.close()
return this_access_token
except Exception as e:
print(e)
# 获取token函数,文本里记录的token失效时调用
def get_access_token():
get_token_url = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s' % (corp_id, corp_secret)
print(get_token_url)
r = requests.get(get_token_url)
request_json = r.json()
this_access_token = request_json['access_token']
print(this_access_token)
r.close()
# 把获取到的access_token写入文本
try:
f = open(file_path,'w+')
f.write(this_access_token)
f.close()
except Exception as e:
print(e)
# 返回获取到的access_token值
return this_access_token
# snedMessage
# 死循环,直到消息成功发送
flag = True
while(flag):
# 从文本获取access_token
access_token = get_access_token_from_file()
try:
to_user = '@all'
message = sys.argv[3]
send_message_url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s' % access_token
print(send_message_url)
message_params = {
"touser":to_user,
"msgtype":"text",
"agentid":agent_id,
"text":{
"content" : message
},
"safe":0
}
r = requests.post(send_message_url, data=json.dumps(message_params))
print('post success %s ' % r.text)
# 判断是否发送成功,如不成功则跑出异常,让其执行异常处理里的函数
request_json = r.json()
errmsg = request_json['errmsg']
if errmsg != 'ok': raise
# 消息成功发送,停止死循环
flag = False
except Exception as e:
print(e)
access_token = get_access_token()
注释:当前发送对象为‘@all’,可修改启动参数进行,获取对应的对象(企业微信的用户ID)后进行发送。
在上传服务器指定文件夹后,可在服务器环境中运行python对脚本进行检验。(xxxx.py为微信脚本)
python3 xxxx.py '参数1' '参数2'
日志输出为:
python3 gzh_wechat.py 'openidxxxxxxxxxxxxxxx'
get success 43_fhNx5B49qQOjvTr-7fY8JBFerQG6n164H45WT1NDccGlEdIvSPIsG1CnsZ377E2VEMlA7D4k55iaawzzip7YIISlly3KcZXnt_gfV6J6kZOS60gnz1HxQ0fI3QgIrRxuvhTxYp7ebA1d0yBlLSIaAFAHOE
https://qyapi.weixin.qq.com/cgi-bin/message/template/send?access_token=43_fhNx5B49qQOjvTr-7fY8JBFerQG6n164H45WT1NDccGlEdIvSPIsG1CnsZ377E2VEMlA7D4k55iaawzzip7YIISlly3KcZXnt_gfV6J6kZOS60gnz1HxQ0fI3QgIrRxuvhTxYp7ebA1d0yBlLSIaAFAHOE
post success {"errcode":0,"errmsg":"ok","msgid":1803177490043944963}
配置ZABBIX - 管理 - 报警媒介类型 - 创建媒体类型
image上图Script parameters表示调用脚本时向脚本传入什么参数,参数解释如下
{ALTER.SENDTO} # 发送给谁,该参数在邮件告警中有作用,但微信告警中没有
{ALTER.SUBJECT} # 告警标题,该参数在邮件告警中有作用,但微信告警中没有
{ALTER.MESSAGE} # 告警内容,在微信告警中有用
- 修改告警内容格式
修改告警内容样式,让告警内容看得更舒服(在微信告警中告警标题是没用的,发送给谁也是基本上没有用)
如下图所示:
image企业号通信录
把所有要接收告警的人都添加到企业号通信录里面,逻辑是(先在通信录里创建该成员,再邀请该成员加入,或让他扫码加入)
如下图所示:
image到此企业微信通知Over。
二、微信公众号消息推送(python)
提前准备内容
app_id、app_secret(微信公众号管理后台获取)
template_id(微信公众号管理后台 - 模板Id),及模板内容参数。
实现步骤
具体配置内容于相同企业微信相同,具体步骤如上;
代码脚本
#!/usr/bin/python3
import requests
import json
import sys
# 企业号及应用相关信息
app_id = 'xxxxxxxx'
app_secret = 'xxxxxxxxxxxxxxxx'
# 存放access_token文件路径
file_path = '/tmp/access_token.log'
def get_access_token_from_file():
try:
f = open(file_path,'r+')
this_access_token = f.read()
print('get success %s' % this_access_token)
f.close()
return this_access_token
except Exception as e:
print(e)
# 获取token函数,文本里记录的token失效时调用
def get_access_token():
get_token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s' % (app_id, app_secret)
print(get_token_url)
r = requests.get(get_token_url)
request_json = r.json()
this_access_token = request_json['access_token']
print(this_access_token)
r.close()
# 把获取到的access_token写入文本
try:
f = open(file_path,'w+')
f.write(this_access_token)
f.close()
except Exception as e:
print(e)
# 返回获取到的access_token值
return this_access_token
# snedMessage
# 死循环,直到消息成功发送
flag = True
while(flag):
# 从文本获取access_token
access_token = get_access_token_from_file()
to_user = sys.argv[1]
subject = sys.argv[2]
message = sys.argv[3]
try:
send_message_url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s' % access_token
print(send_message_url)
message_params = {
"touser": to_user,
"template_id":"-CUCjl5B1CEb_QxZFZABZ2erzz_kbLoJFiIhi3PcWaQ",
"data":{
"first" : {
"value":subject,
"color":"#173177"
},
"keyword1" : {
"value":message,
"color":"#173177"
},
"keyword2" : {
"value":"39.8元",
"color":"#173177"
},
"remark":{
"value":"欢迎再次购买!",
"color":"#173177"
}
}
}
r = requests.post(send_message_url, data=json.dumps(message_params))
print('post success %s ' % r.text)
# 判断是否发送成功,如不成功则跑出异常,让其执行异常处理里的函数
request_json = r.json()
errmsg = request_json['errmsg']
if errmsg != 'ok': raise
# 消息成功发送,停止死循环
flag = False
except Exception as e:
print(e)
access_token = get_access_token()
重点说明
1.上传应用服务器中文件夹,脚本位置如下:
image-20210331102107672.png2.文件上传后需给脚步文件操作权限,当前我勾选了所有权限:
image-20210331102257020.png或者输入
chmon u+x xxxx.py
(如果给予权限后,依然提示权限问题一调要重启服务器)
重启命令:
reboot
3.脚本代码中特别需要注意,在安装python后要找到配置python环境的启动文件,我当前的是
/usr/bin/python3
(该路径会运用到python脚本的启动项)
如果找不到可以使用如下语句检索:
whereis python3
4.在复制脚本到指定位置后,且安装了Python后,一定要执行如下语句,安装脚本所需依赖:
pip3 install requests
python3 --version
pip3 --version
3.微信公众号消息推送(shell)
提前准备内容
app_id、app_secret(微信公众号管理后台获取)
template_id(微信公众号管理后台 - 模板Id),及模板内容参数。
实现步骤
具体配置内容于相同企业微信相同,具体步骤如上;
代码脚本
#!/bin/sh
# 微信消息发送脚本
#全局配置--
#微信公众号appID
appID=xxxxxx
#微信公众号appsecret
appsecret=xxxxxxx
#微信公众号发送消息模板
tpl_id=-xxxxxxxxxxxx
#消息模板:
# {{first.DATA}}
# 代办事项:{{keyword1.DATA}}
# 提醒时间:{{keyword2.DATA}}
#
# {{remark.DATA}}
#获取微信公众号AccessToken,并缓存到本地 函数
getAccessToken(){
if [ -f "/var/log/zabbix/.wechat_accesstoken" ]; then
access_token=`cat /var/log/zabbix/.wechat_accesstoken | awk -F":" '{print $1}'`
expires_in=`cat /var/log/zabbix/.wechat_accesstoken | awk -F":" '{print $2}'`
time=`cat /var/log/zabbix/.wechat_accesstoken | awk -F":" '{print $3}'`
if [ -z $access_token ] || [ -z $expires_in ] || [ -z $time ]; then
rm -f /var/log/zabbix/.wechat_accesstoken
getAccessToken
fi
else
content=$(curl "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appID&secret=$appsecret")
# echo "get content: $content"
access_token=`echo $content | awk -F "\"" '{print $4}'`
expires_in=`echo $content | awk -F "\"" '{print $7}' | cut -d"}" -f1|cut -c2-`
echo "access_token = $access_token" >> /var/log/zabbix/.wechat_accesstoken_log
# echo "expires_in = $expires_in"
time=$(date +%s)
echo "$access_token:$expires_in:$time" > /var/log/zabbix/.wechat_accesstoken
if [ -z $access_token ] || [ -z $expires_in ] || [ -z $time ]; then
echo "not get access_token" >> /var/log/zabbix/.wechat_accesstoken_log
exit 0
fi
fi
remain=$[$(date +%s) - $time]
echo "remain:$remain">> /var/log/zabbix/.wechat_accesstoken_log
limit=$[$expires_in - 7020]
echo "limit:$limit">> /var/log/zabbix/.wechat_accesstoken_log
if [ $remain -gt $limit ]; then
rm -f /var/log/zabbix/.wechat_accesstoken
getAccessToken
fi
}
#发送消息函数
sendMessage(){
#消息json体
message=`cat << EOF
{
"touser":"$openid",
"template_id":"$tpl_id",
"url":"$url",
"data":{
"first": {
"value":"$first",
"color":"#FF0000"
},
"keyword1":{
"value":"$keyword1",
"color":"#173177"
},
"keyword2": {
"value":"$keyword2",
"color":"#173177"
},
"remark":{
"value":"$remark",
"color":"#FF0000"
}
}
}
EOF
`
info=`curl -X POST -H "Content-Type: application/json" https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$access_token -d "$message"`
echo "info:$info">> /var/log/zabbix/.wechat_accesstoken_log
}
#帮助信息函数
#usage(){
# cat <<EOF
#usage: $0 [-u openids -s summary -n name -t time -d detail -l link] [-h]
# u wechat user openid , multiple comma separated
# s message summary
# n project name
# t alarm time
# d message detail
# l link address
# h output this help and exit
#EOF
#}
#获取脚本执行参数
#while getopts ":u:s:n:t:d:h:l:" op; do
# case $op in
# u)openids="$OPTARG";;
# s)first="$OPTARG";;
# n)name="$OPTARG";;
# t)date="$OPTARG";;
# d)remark="$OPTARG";;
# l)url="$OPTARG";;
# *)
# usage
# exit 0
# ;;
# esac
#done
#判断条件满足发送消息
if [[ -n $1 && -n $2 && -n $3 && -n $4 ]]; then
url=$2
first=$3
keyword1=$4
keyword2=$5
remark=$6
echo `date +"%Y-%m-%d %H:%M:%S"` >> /var/log/zabbix/.wechat_accesstoken_log
echo "send message : $url $openid $first $keyword1 $keyword2 $remark" >> /var/log/zabbix/.wechat_accesstoken_log
getAccessToken
OLD_IFS="$IFS"
IFS=","
arr=($1)
IFS="$OLD_IFS"
for openid in ${arr[@]}
do
sendMessage
done
exit $?
else
echo `date +"%Y-%m-%d %H:%M:%S"` >> /var/log/zabbix/.wechat_accesstoken_log
echo "error." >> /var/log/zabbix/.wechat_accesstoken_log
# usage
exit 1
fi
2.配置脚本触发器及动作
具体配置流程:
1.用户篇
1.1管理 -> 用户 -> 创建用户
添加用户.png1.2为用户添加报警媒介
添加报警媒介.png 赋值报警媒介.png1.3给予用户权限(一定市Super admin,用户类型:Super admin)
用户权限.png2.触发器(配置 - 主机 - 触发器)
2.1 选择主机 - 点击列表中触发器 - 点击创建触发器
触发器001.png2.2 添加触发器
触发器002.png注意:
表达式的编写;
问题事件生成模式:1.单个(只触发响应一下动作操作及脚本);2.多重(一定时间会重复响应动作操作及脚本)
允许手动关闭(否则后期在关闭是无法进行手动操作,需选中);
点击已启用/已关闭可以直接切换状态;
3.动作篇(配置 - 动作)
3.1 添加动作(可添加多个动作进行“或”,“与”,“非”的操作排列)
添加动作-1.png3.2 动作 - 操作
添加动作-操作步骤01.png 添加动作-操作步骤02.png故障{TRIGGER.STATUS},服务器:{HOSTNAME1}发生: {TRIGGER.NAME}故障!
告警主机:{HOSTNAME1}
告警时间:{EVENT.DATE} {EVENT.TIME}
告警等级:{TRIGGER.SEVERITY}
告警信息: {TRIGGER.NAME}
告警项目:{TRIGGER.KEY1}
问题详情:{ITEM.NAME}:{ITEM.VALUE}
当前状态:{TRIGGER.STATUS}:{ITEM.VALUE1}
事件 ID:{EVENT.ID}
动作操作-003.png服务器:{HOST.NAME}: {TRIGGER.NAME}已恢复!
告警主机:{HOST.NAME}
告警地址:{HOST.IP}
监控项目:{ITEM.NAME}
监控取值:{ITEM.LASTVALUE}
告警等级:{TRIGGER.SEVERITY}
当前状态:{TRIGGER.STATUS}
告警信息:{TRIGGER.NAME}
告警时间:{EVENT.DATE} {EVENT.TIME}
恢复时间:{EVENT.RECOVERY.DATE} {EVENT.RECOVERY.TIME}
持续时间:{EVENT.AGE}
事件ID:{EVENT.ID}
最后添加完千万不要忘记更新。
参考文献:zabbix4.2配置微信告警脚本教程 https://idc.wanyunshuju.com/zab/1028.html