关键词:Cacti、微信告警
摘要:现实生产环境中,我们通常使用邮件和短信接受cacti告警信息,但是邮件经常被工作人员搁置在角落中甚至被设置为垃圾邮件被过滤掉;而公司的短信接口又太贵,复杂环境中使用短息告警会使运维成本增加很多。微信提供了很好的第三方接口,我们可以利用微信告警以求降低运维成本。
案例描述
本案例以实际实现cacti微信告警来完成整个过程的撰写
案例分析
本案例以微信企业号推送消息的形式来推送cacti告警,只需要在原有cacti告警机制的基础上修改部分代码即可实现,节约成本的同时也增加了告警方式的多样性
3 解决过程
3.1申请微信企业公众号
1、申请微信企业公众号https://qy.weixin.qq.com/,填写基本信息,需使用邮箱注册
2、邮箱收到验证邮件后激活帐号
3、选择类型为企业号,群发消息没有限制
4、信息登记选择团体,这样不需要企业组织机构代码等信息,只需要实名和手机认证即可,减少了很多不必要的麻烦,但同时也能够满足基本的需求
-
填写微信企业公众号相关信息之后,公众号即可申请成功
3.2微信企业公众号设置
1、通讯录中添加子部门
2、通讯录中添加成员,然后邀请成员关注(注意:微信企业公众号需要通过管理者的邀请才能关注该企业公众号,直接扫码关注是无法关注成功的,只有在通讯录的用户且信息匹配才能关注成功)
首先新增成员
成员添加成功后即可邀请关注,可通过将二维码分享给成员
3、应用中心添加应用,通过应用发送消息给部门成员
添加消息型应用
设置可见范围
注意:此处应用ID很重要,后面会用到
4、新建普通管理组,获取CorpID和Secret,并赋予相应的权限
设置--->功能设置---->权限管理---->新建普通管理组
设置权限,可以设置通讯录权限和应用权限
设置通讯录权限
设置应用权限
保存后获取到CorpID和Secret,并获取到相应的权限
3.3验证微信企业公共号发送消息功能
-
使用发消息功能直接发送消息功能
-
使用企业号开发者中心接口文档来验证发送消息功能
使用CorpID和Secret获取access_token
使用access_token调用接口,发送消息
此处body内容可参考文档接口中的发送消息中的消息类型及数据格式进行更改
参数 |
必须 |
说明 |
touser |
否 |
成员ID列表(消息接收者,多个接收者用'|'分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送 |
toparty |
否 |
部门ID列表,多个接收者用'|'分隔,最多支持100个。当touser为@all时忽略本参数 |
totag |
否 |
标签ID列表,多个接收者用'|'分隔,最多支持100个。当touser为@all时忽略本参数 |
msgtype |
是 |
消息类型,此时固定为:text (支持消息型应用跟主页型应用) |
agentid |
是 |
企业应用的id,整型。可在应用的设置页面查看 |
content |
是 |
消息内容,最长不超过2048个字节,注意:主页型应用推送的文本消息在微信端最多只显示20个字(包含中英文) |
safe |
否 |
表示是否是保密消息,0表示否,1表示是,默认0 |
{ "touser":"@all", "toparty":"@all", "totag":"@all", "msgtype":"text", "agentid":"1", # agentid是在添加应用中的ID号 "text":{ "content":"This is a test message" }, "safe":"0" } |
此时查看已关注该企业公众号的微信,会收到相应的消息
3.4设置cacti实现微信告警
1、将cacti中thold的报警内容导出至文本文件进行保存
进入cacti主目录, vim plugins/thold/thold_functions.php
查找2839行$text位置 上方插入语句
$msg_wx = strip_tags(str_replace('<br>', "\n", $message)); //删除message中的html标签,并将<br>替换为换行符\n $msg_wx = trim($msg_wx); //整理msg_wx字符串 $msg_wx = iconv( "GB2312//IGNORE", "UTF-8", $msg_wx); //转换编码为utf-8,防止乱码 $sub_wx = iconv( "GB2312//IGNORE", "UTF-8", $subject); //转换编码为utf-8,防止乱码 $file_title = '/tmp/title.txt'; //要写入文件的文件名(可以是任意文件名),如果文件不存在,将会创建一个 $file_message = '/tmp/message.txt'; //要写入文件的文件名(可以是任意文件名),如果文件不存在,将会创建一个 if($f = file_put_contents($file_title, $sub_wx)) //将subject参数的值保存到file_title中 if($f = file_put_contents($file_message, $msg_wx)) //将msg_wx参数的值保存到file_message中 shell_exec("/etc/wechat.sh"); //运行wechat.sh文件,进行微信报警操作 |
2、创建微信发送脚本
touch /etc/wechat.sh
chmod +x /etc/wechat.sh
wechat.sh中插入以下内容
#微信企业号发送消息脚本 #!/bin/bash CropID='wx60xxxxxxxxx2f9fa' #此处CropID请根据实际情况填写 Secret='olJZsHEb3ihsB5NQgeQxheXXXXXXXBpvG-Rrj04XhI0daMP7ca5FKRLbw6' #此处Secret请根据实际情况填写 GURL="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$CropID&corpsecret=$Secret" Gtoken=$(/usr/bin/curl -s -G $GURL | awk -F\" '{print $4}') PURL="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$Gtoken" function body() { local int AppID=1 #Appid 填写企业号中建立的报警APP的ID Ent=$'\n' Date=$(date '+%Y年%m月%d日 %H:%M:%S\n\n') #添加Cacti微信报警日期参数 Tit=$(cat /tmp/title.txt) #读取/tmp/title文件中内容到变量Tit Msg=$Date$Tit$Ent$(cat /tmp/message.txt|sed 's/%//g') #拼接msg主体文件,包含日期,主题,报警内容.并删除报警内容中的'%'号. Url=$(grep "http" /tmp/message.txt|sed 's/URL: //g') #获取message.txt中的url行内容 Pic_tmp=$(grep "http" /tmp/message.txt|sed 's/URL: //g'|sed 's/\/graph.php/\/graph_image.php/g') if [ ! -n "$Pic_tmp" ] ;then Pic="" else Pic=$Pic_tmp$'&graph_height=130&graph_width=420&t='$Date fi #根据url行内容修改为添加Pic参数 #在此修改图片大小,防止图像显示不全,并判断图片文件是否存在。防止宕机出现图片报警 printf '{\n' printf '\t"touser": "'"@all"\"",\n" printf '\t"toparty": "'"@all"\"",\n" printf '\t"totag": "'"@all"\"",\n" printf '\t"msgtype": "news",\n' #使用news消息类型 printf '\t"agentid": "'" $AppID "\"",\n" printf '\t"news": {\n' printf '\t"articles": [\n' printf '{\n' printf '\t\t"title": "'"$Tit"\","\n" printf '\t\t"description": "'"$Msg"\","\n" printf '\t\t"url": "'"$Url"\","\n" printf '\t\t"picurl": "'"$Pic"\","\n" printf '\t}\n' printf '\t]\n' printf '\t}\n' printf '}\n' } /usr/bin/curl --data-ascii "$(body )" $PURL #传送凭证调用企业号接口 |
body内容可参考文档接口中的发送消息中的消息类型及数据格式进行更改
参数 |
必须 |
说明 |
touser |
否 |
成员ID列表(消息接收者,多个接收者用'|'分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送 |
toparty |
否 |
部门ID列表,多个接收者用'|'分隔,最多支持100个。当touser为@all时忽略本参数 |
totag |
否 |
标签ID列表,多个接收者用'|'分隔,最多支持100个。当touser为@all时忽略本参数 |
msgtype |
是 |
消息类型,此时固定为:news (不支持主页型应用) |
agentid |
是 |
企业应用的id,整型。可在应用的设置页面查看 |
articles |
是 |
图文消息,一个图文消息支持1到8条图文 |
title |
否 |
标题,不超过128个字节,超过会自动截断 |
description |
否 |
描述,不超过512个字节,超过会自动截断 |
url |
否 |
点击后跳转的链接。 |
picurl |
否 |
图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80。如不填,在客户端不显示图片 |
3、修改graph_image.php文件,取消graph_image.php的认证,否则微信无法正常显示图片
#include("./include/auth.php"); include_once("./lib/rrd.php"); include("./include/global.php"); api_plugin_hook_function('graph_image'); |
4、以下是微信告警信息与手机邮箱收到的告警信息对比
微信告警消息 邮件告警消息
4 解决结果
通过参考本案例,可以完成实现cacti的微信告警功能,增加了告警方式,实现多种告警方式并存
5 总结
本案例方法是通过命令抓取邮件告警的标题和内容然后调用微信企业公众号发送消息接口来实现微信告警,因此需要在创建阀值的时候添加告警邮箱,并配置好邮件服务器,保证触发阈值告警后邮箱能收到告警邮件,如果没有告警邮件的话,微信报警也是不生效的。