我有一个 Zabbix 是收 HomeLab 告警的,之前注册了一个企业微信拉了个群通过 Bot 去发告警,但是因为工作也是使用企业微信,基本上我都在我的主企业里,企业微信有个特性是不提醒其他企业的具体消息,搞得我上周漏掉了服务器硬盘挂了告警,本来是周四就告警预故障了,结果周六才看到。好在网上能买到备件,周日到货完成了更换,才没有出现两块硬盘接连“寄”掉的事情发生。

从这件事情之后,我就想如何换一种告警渠道,避免看不到告警的情况出现。最后发现可以在企业微信中添加内部应用,结合微信企业号去推送告警。

添加企业微信应用

应用管理创建一个应用,并获取到 Secret 和 AgentId。这里的 Secret 对应后面的 Corpsecret。
20220409221403

微信添加微信插件(原企业号)

之前以为企业号=企业微信,最近再翻管理后台发现企业号变成了微信插件。我们可以在我的企业->微信插件中获得二维码并关注。

20220409220634

增加报警媒介类型

增加一种报警媒介,类型是 WebHook,参数如下填写:

参数 参数说明
Agentid 应用的 ID
Corpid 企业 ID 术语说明-corpid
Corpsecret 应用的凭证密钥 术语说明-secret
Subject 告警主题 {ALERT.SUBJECT}
Message 告警内容 {ALERT.MESSAGE}
To 告警接收人 {ALERT.SENDTO}

20220409214306

脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
var weworkApp = {
touser: null,
message: null,
corpid: null,
corpsecret: null,
agentid: null,
proxy: null,
msgtype: "text",

// 获取企业微信 AccessToken
getAccessToken: function () {
var url =
"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" +
weworkApp.corpid +
"&corpsecret=" +
weworkApp.corpsecret,
request = new CurlHttpRequest();

// 设置代理
if (weworkApp.proxy) {
request.setProxy(weworkApp.proxy);
}
request.AddHeader("Content-Type: application/json");
response = request.Get(url);
try {
response = JSON.parse(response);
return response.access_token;
} catch (error) {
response = null;
}
if (request.Status() !== 200 || response.errcode !== 0) {
if (typeof response.errmsg === "string") {
throw response.errmsg;
} else {
throw "Unknown error. Check debug log for more information.";
}
}
},

// 发消息
sendMessage: function (access_token) {
var params = {
touser: weworkApp.touser,
agentid: weworkApp.agentid,
msgtype: weworkApp.msgtype,
text: {
content: weworkApp.message,
},
enable_duplicate_check: 1,
duplicate_check_interval: 20,
},
data,
response,
request = new CurlHttpRequest(),
url =
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" +
access_token;

// 设置代理
if (weworkApp.proxy) {
request.setProxy(weworkApp.proxy);
}

request.AddHeader("Content-Type: application/json");
data = JSON.stringify(params);

// 在日志中不展示 AccessToken
Zabbix.Log(
4,
"[weworkApp Webhook] URL: " +
url.replace(weworkApp.access_token, "<ACCESS_TOKEN>")
);
Zabbix.Log(4, "[weworkApp Webhook] params: " + data);
response = request.Post(url, data);
Zabbix.Log(4, "[weworkApp Webhook] HTTP code: " + request.Status());

try {
response = JSON.parse(response);
} catch (error) {
response = null;
}

if (request.Status() !== 200 || response.errcode !== 0) {
if (typeof response.errmsg === "string") {
throw response.errmsg;
} else {
throw "Unknown error. Check debug log for more information.";
}
}
},
};

// Main
try {
var params = JSON.parse(value);
if (params.HTTPProxy) {
weworkApp.proxy = params.HTTPProxy;
}
weworkApp.agentid = params.Agentid;
weworkApp.corpid = params.Corpid;
weworkApp.corpsecret = params.Corpsecret;
weworkApp.touser = params.To;
var access_token = weworkApp.getAccessToken();
weworkApp.message = params.Subject + "\n" + params.Message;
weworkApp.sendMessage(access_token);
return "OK";
} catch (error) {
Zabbix.Log(4, "[weworkApp Webhook] notification failed: " + error);
throw "Sending failed: " + error + ".";
}

当时测试了推送 makedown,但是发现微工作台(原企业号)不支持展示 markdown 消息。

在添加完脚本后还应添加对应的模板消息,并将告警媒介关联到某个动作上。

我们通过用户设置页的告警媒介,关联上 WeworkApp 这个媒介和接收告警的用户。

20220409234248

告警测试

搞点事情,触发一下告警。完美~

20220409215510

扩展阅读