---
title: "Zabbix 企业微信告警"
date: 2019-10-29T21:26:35+08:00
lastmod: 2021-04-11T01:00:00+08:00
keywords: []
tags: ["zabbix", "微信", "告警"]
categories: ["zabbix"]
---

## 环境
- CentOS7，docker-ce 20.0
- 启动 zabbix5 容器
    ```bash
    docker run -d \
        --net host \
        --name zabbix \
        harbor.colben.cn/general/alpine-zabbix
    ```

- 打开浏览器，访问 http://ip/zabbix/，打开 zabbix web 安装界面
- 不要做任何修改，一直下一步，直到打开 zabbix 登陆页面，默认 Admin/zabbix

## 部署脚本
- 进入 zabbix 容器中
- 安装 jq 命令
- 修改 /etc/zabbix/zabbix_server.conf，配置告警脚本加载位置
    ```
    AlertScriptsPath=/var/log/zabbix/alertscripts
    ```

- 创建 /var/log/zabbix/alertscripts/wechat.sh，内容如下
    ```bash
    set -euo pipefail
    export LANG=en_US.UTF-8
    trap Quit EXIT
    
    # 企业 ID
    CORP_ID='ww11112222aaaabbbb'
    # 应用 Secret
    CORP_SECRET='ABCDefghIJKLmnopQRSTuvwxYZ0000111122223333U'
    # 应用 ID
    AGENT_ID='1000002'
    # 多个用户之间用"| 间隔
    TO_USER='@all'
    # 部门 ID
    TO_PARTY='1'
    # token 文件存放位置
    TOKEN_FILE='/tmp/wechat_token'
    
    function Print {
        echo -e "$(date +'[%F %T] INFO') $*"
    }
    
    function Warn {
        echo -e "$(date +'[%F %T] WARN') $*"
    }
    
    function Error {
        echo -e "$(date +'[%F %T] ERRRO') $*"
        exit 1
    }
    
    function Quit {
        [ 0 -ne $? ] && rm -f $TOKEN_FILE && Error Failed to alert!
        [ -z "${END:-}" ] && echo && Error Interrupted manually!
        Print Succeeded to alert.
    }
    
    function RequestToken {
        Warn Request token ...
        date +%s > $TOKEN_FILE
        local response=$(curl -sSL \
            "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$CORP_ID&corpsecret=$CORP_SECRET")
        local errcode=$(echo "$response" | jq -erM .errcode)
        local errmsg=$(echo "$response" | jq -erM .errmsg)
        [ 0 -ne $errcode -a 'ok' != "$errmsg" ] && Error Request token failed: $errcode, $errmsg!
        echo $response | jq -erM .access_token >> $TOKEN_FILE
    }
    
    function GetToken {
        [ ! -e $TOKEN_FILE ] && RequestToken && return
        Warn Get token from localfile ...
        local now=$(date +%s)
        local token="$(sed -n 2p $TOKEN_FILE)"
        local token_time=$(sed -n 1p $TOKEN_FILE)
        if [ $((now-token_time)) -gt 7200 ]; then
            Warn Local token expired ...
            RequestToken
        fi
    }
    
    function SendMsg {
        Warn Send message: $1 ...
        local token=$(sed -n 2p $TOKEN_FILE)
        local response=$(curl -sSL -X POST \
            -H "Content-Type: application/json" \
            "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=$token" \
            -d @- <<-EOF
    {
      "touser": "$TO_USER",
      "toparty": "$TO_PARTY",
      "msgtype": "text",
      "agentid": "$AGENT_ID",
      "text": {
        "content": "$1\n$2"
      },
      "safe": 0
    }
    EOF
    )
        local errcode=$(echo "$response" | jq -erM .errcode)
        local errmsg="$(echo "$response" | jq -erM .errmsg)"
        [ 0 -eq $errcode -o 'ok' = "$errmsg" ] || Error Send msg failed: $errcode, $errmsg!
    }
    
    # Start here
    GetToken
    SendMsg "$1" "$2"
    END=1
    ```

- 重启 zabbix 容器
- 测试脚本，如果企业微信能收到信息则表示脚本正常
    ```bash
    /var/log/zabbix/alertscripts/wechat.sh test_subject test_content
    ```

## 配置 zabbix
- 浏览器登陆 zabbix
- 单击"管理"-"报警媒介类型"-"创建媒体类型"，输入如下信息
    - 名称: 企业微信
    - 类型: 脚本
    - 脚本名称: wechat.py
    - 脚本参数:
        - {ALERT.SUBJECT}
        - {ALERT.MESSAGE}
    - 其它默认，单击"添加"
- 单击"管理"-"用户"-"Admin"-"报警媒介"-"添加"，输入如下信息
    - 类型: 企业微信
    - 收件人: 这一项用不到了，随便写 ...
    - 其它默认，单击"添加"
- 单击"配置"-"动作"-"Report problems to Zabbix administrators"
    - 在"动作"标签页下，选中"已启用"
    - 在"操作"标签页下，输入如下信息
        - 默认标题:
            ```
            XXXX系统 {HOST.NAME} 故障: {TRIGGER.NAME}
            ```
        - 消息内容:
            ```
            服务器: {HOST.NAME}\n
            故障时间: {EVENT.DATE} {EVENT.TIME}\n
            故障名称: {TRIGGER.NAME}\n
            故障状态: {TRIGGER.STATUS}\n
            故障等级: {TRIGGER.SEVERITY}\n
            故障编号: ID: {EVENT.ID}\n
            监控项: {ITEM.NAME1} ({HOST.NAME1}:{ITEM.KEY1})\n
            监控值:\n
            {ITEM.VALUE1}
            ```
        - 单击"操作"框中的"编辑"，打开"操作细节"框，输入如下信息
            - 操作类型: 发送消息
            - 发送到用户: "添加" Admin 用户
            - 仅送到: 企业微信
            - 其他默认，单击"更新"
    - 在"恢复操作"标签页下，输入如下信息
        - 默认标题:
            ```
            XXXX系统 {HOST.NAME} 恢复: {TRIGGER.NAME}
            ```
        - 消息内容:
            ```
            服务器: {HOST.NAME}\n
            恢复时间: {EVENT.DATE} {EVENT.TIME}\n
            故障名称: {TRIGGER.NAME}\n
            故障状态: {TRIGGER.STATUS}\n
            故障等级: {TRIGGER.SEVERITY}\n
            故障编号: ID: {EVENT.ID}\n
            监控项: {ITEM.NAME1} ({HOST.NAME1}:{ITEM.KEY1})\n
            监控值:\n
            {ITEM.VALUE1}
            ```
        - 单击"操作"框中的步骤1的"编辑"，打开"操作细节"框，输入如下信息
            - 操作类型: 发送消息
            - 发送到用户: "添加" Admin 用户
            - 仅送到: 企业微信
            - 其他默认，单击"更新"
    - 忽略"更新操作"
    - 其他默认，单击"更新"

