提交 0c99c1f3 authored 作者: 陈泽健's avatar 陈泽健

feat(monitoring): 添加钉钉通知功能并优化报告发送

- 移除 lph@huazhaochina.com 邮件接收人
- 添加钉钉机器人配置参数(access token 和 secret)
- 实现钉钉消息发送功能,包括 URL 构造和 HMAC-SHA256 签名
- 添加钉钉消息内容转义和 JSON 格式化处理
- 在主流程中集成钉钉通知发送
- 更新邮件配置生成的描述文本
- 优化监控流程,移除未使用的 pandoc 依赖检查
- 添加监控状态汇总和摘要信息生成
- 实现异常状态判断和 emoji 标识显示
上级 a9335f8f
......@@ -17,7 +17,7 @@ WORD_REPORT_DIR="./monitor_reports_word"
HOST_NAME="$(hostname)"
# 邮件通知配置
MAIL_TO="czj@huazhaochina.com,lph@huazhaochina.com,pgy@huazhaochina.com"
MAIL_TO="czj@huazhaochina.com,pgy@huazhaochina.com"
MAIL_SUBJECT_PREFIX="自动化服务监测报告"
# SMTP 服务器配置(QQ 企业邮箱)
......@@ -27,6 +27,15 @@ MAIL_SMTP_SSL_SCHEME="smtps" # s-m-t-p-s 协议
MAIL_SMTP_USER="czj@huazhaochina.com"
MAIL_SMTP_PASS="Ubains@123"
# 钉钉机器人配置(自定义机器人 -> 安全设置 -> 加签)
# 自定义机器人 -> 安全设置 -> 加签
DINGDING_ACCESS_TOKEN="7fbf40798cad98b1b5db55ff844ba376b1816e80c5777e6f47ae1d9165dacbb4"
DINGDING_SECRET="SEC610498ed6261ae2df1d071d0880aaa70abf5e67efe47f75a809c1f2314e0dbd6"
# 不需要 @ 人就都留空/false
DINGDING_AT_MOBILES=""
DINGDING_AT_ALL="false"
#################### 日志 ####################
log() {
local level="$1"; shift
......@@ -151,6 +160,141 @@ EOF
return 0
}
#################### 7. 钉钉发送(纯 Bash + openssl + curl) ####################
# 构造最终的钉钉 Webhook URL(access_token + timestamp + sign)
build_dingtalk_url() {
local access_token="$1"
local secret="$2"
if [[ -z "$access_token" ]]; then
echo ""
return 1
fi
# 毫秒时间戳
local timestamp
timestamp="$(printf '%s000' "$(date +%s)")"
# 如果没启用加签(secret 为空),只拼 access_token + timestamp
if [[ -z "$secret" ]]; then
echo "https://oapi.dingtalk.com/robot/send?access_token=${access_token}&timestamp=${timestamp}"
return 0
fi
# string_to_sign = timestamp + "\n" + secret
local string_to_sign="${timestamp}"$'\n'"${secret}"
# HMAC-SHA256 + base64
local sign_raw
sign_raw="$(printf '%s' "$string_to_sign" \
| openssl dgst -sha256 -hmac "$secret" -binary \
| openssl base64)"
# URL 编码 —— 严格对齐 Python 的 urllib.parse.quote_plus
# 规则:
# 1. 字母/数字/.-_/~ 保留
# 2. 空格 -> +
# 3. 其它字符(包括 +、/、= 等)都转成 %XX
local sign_enc=""
local i ch hex
for ((i=0; i<${#sign_raw}; i++)); do
ch="${sign_raw:$i:1}"
case "$ch" in
[a-zA-Z0-9.~_-])
sign_enc+="$ch"
;;
' ')
sign_enc+="+"
;;
*)
printf -v hex '%%%02X' "'$ch"
sign_enc+="$hex"
;;
esac
done
echo "https://oapi.dingtalk.com/robot/send?access_token=${access_token}&timestamp=${timestamp}&sign=${sign_enc}"
return 0
}
# 发送 text 消息到钉钉
# 使用方式:先构造 DD_TEXT,然后执行:
# DD_TEXT="$dd_text" send_dingtalk_markdown
send_dingtalk_markdown() {
local access_token="${DINGDING_ACCESS_TOKEN:-}"
local secret="${DINGDING_SECRET:-}"
local at_mobiles="${DINGDING_AT_MOBILES:-}"
local at_all="${DINGDING_AT_ALL:-false}"
local content="${DD_TEXT:-}"
if [[ -z "$access_token" ]]; then
log ERROR "[钉钉发送] 未配置 DINGDING_ACCESS_TOKEN,跳过发送。"
return 1
fi
if [[ -z "$content" ]]; then
log ERROR "[钉钉发送] DD_TEXT 为空,跳过发送。"
return 1
fi
local url
url="$(build_dingtalk_url "$access_token" "$secret")" || {
log ERROR "[钉钉发送] 构造 Webhook URL 失败,跳过发送。"
return 1
}
# 组装 @ 信息
local at_json=""
if [[ -n "$at_mobiles" ]]; then
local tmp arr mobile_items m
tmp="$(echo "$at_mobiles" | tr ',' ' ')"
# shellcheck disable=SC2206
arr=($tmp)
for m in "${arr[@]}"; do
[[ -z "$m" ]] && continue
if [[ -n "$mobile_items" ]]; then
mobile_items="${mobile_items},\"${m}\""
else
mobile_items="\"${m}\""
fi
done
at_json="\"at\": {\"atMobiles\": [${mobile_items}], \"isAtAll\": ${at_all} }"
else
at_json="\"at\": {\"isAtAll\": ${at_all} }"
fi
# 对正文做简单 JSON 转义(换行和双引号)
local json_content
json_content="${content//$'\\'/'\\\\'}" # 反斜杠
json_content="${json_content//$'"'/'\"'}" # 双引号
json_content="${json_content//$'\n'/\\n}" # 换行 -> \n
# 构造 text 消息体
local payload
payload="$(cat <<EOF
{
"msgtype": "text",
"text": {
"content": "${json_content}"
},
${at_json}
}
EOF
)"
# 发送 HTTP 请求
local resp
resp="$(curl -sS -H 'Content-Type: application/json;charset=utf-8' -d "$payload" "$url" 2>>"$LOG_FILE" || true)"
if echo "$resp" | grep -q '"errcode":0'; then
log INFO "[钉钉发送] 已成功发送消息。响应:$resp"
return 0
else
log ERROR "[钉钉发送] 发送失败,响应:$resp"
return 1
fi
}
#################### 1. 平台识别 ####################
detect_platform() {
if [ -d "/data/services" ]; then
......@@ -706,9 +850,8 @@ write_md_report() {
main_run_once() {
log INFO "[启动] 自动化服务监测 Shell 脚本(单次执行模式),目标服务器(本机)=${HOST_NAME}"
# 0. 环境准备:安装依赖 + 生成邮件配置
# 0. 环境准备:只处理邮件依赖和配置
ensure_mailx_installed || log ERROR "[启动] mailx 安装失败,后续邮件发送可能不可用。"
# ensure_pandoc_installed || log ERROR "[启动] pandoc 安装失败,将只生成 Markdown 报告。"
ensure_mailx_smtp_config || log ERROR "[启动] mailx SMTP 配置生成失败,后续邮件发送可能不可用。"
detect_platform
......@@ -723,7 +866,6 @@ main_run_once() {
log INFO "[平台识别] $HOST_NAME => 平台类型=${platform_text} 基路径=${BASE_PATH}"
log INFO "[系统识别] $HOST_NAME => ujava=${HAS_UJAVA} upython=${HAS_UPYTHON} upython_voice=${HAS_UPYTHON_VOICE} 系统=(${SYSTEMS[*]:-})"
log INFO "[心跳] $HOST_NAME: 平台=$([[ "$PLATFORM_TYPE" == "new" ]] && echo || echo ) 基路径=${BASE_PATH} 系统=${SYSTEMS[*]:-}"
resolve_log_targets
......@@ -735,20 +877,66 @@ main_run_once() {
monitor_mem_once
monitor_mysql_once
# (如已经实现)容器信息检测
collect_container_info
# 生成报告,并获取报告文件路径
# 生成报告,并获取报告文件路径(md)
local report_file
report_file="$(write_md_report)"
# 根据第 6 点需求:发送邮件通知
# 6. 邮件发送
send_report_mail "$report_file" || {
log ERROR "[主流程] 报告已生成,但邮件发送失败,请检查日志和邮件客户端配置。"
}
log INFO "[结束] 本次监测已完成,报告已生成并尝试发送邮件。"
# 7. 发送钉钉通知(文本摘要)
local now_time
now_time="$(date '+%Y-%m-%d %H:%M:%S')"
# 汇总整体状态:有暴涨/错误就判为异常
local overall_status="正常"
local overall_emoji="✅"
# 日志暴涨是否异常
local any_log_bad=0
for key in "${!BURST_LAST_RESULT[@]}"; do
case "${BURST_LAST_RESULT[$key]}" in
BURST|ERROR)
any_log_bad=1
break
;;
esac
done
# MySQL 是否暴涨/错误
local mysql_bad=0
case "$MYSQL_LAST_BURST_STATUS" in
BURST|ERROR)
mysql_bad=1
;;
esac
if (( any_log_bad == 1 || mysql_bad == 1 )); then
overall_status="异常"
overall_emoji="❌"
fi
local dd_text
dd_text="【监控】${HOST_NAME} - ${overall_status}${overall_emoji}
触发时间:${now_time}
监控概览:
- 日志审计:${BURST_LAST_DESC[*]:-未采集}
- 内存:当前 ${MEM_LAST_USED_MB} MB,峰值 ${MEM_PEAK_USED_MB} MB
- MySQL:当前连接数 ${MYSQL_LAST_CONN},峰值 ${MYSQL_PEAK_CONN},暴涨状态:${MYSQL_LAST_BURST_STATUS}
- 容器:运行中 $(echo \"$CONTAINER_RUNNING_LIST\" | wc -l) 个,未运行 $(echo \"$CONTAINER_EXITED_LIST\" | wc -l)
系统监控告警通知"
DD_TEXT="$dd_text" send_dingtalk_markdown || {
log ERROR "[主流程] 报告已生成,但钉钉发送失败,请检查 DINGDING_ACCESS_TOKEN / SECRET 配置。"
}
log INFO "[结束] 本次监测已完成,报告已生成并尝试发送邮件与钉钉通知。"
}
#################### 脚本入口 ####################
......
......@@ -67,8 +67,9 @@
1、将本次监测的所有检测项信息输出成markdown格式报告,内容排版需要优美,markdown格式报告发送于钉钉。
2、将本次监测的所有检测项信息输出成word格式报告,内容排版优美,word格式报告发送于邮件。
##### 6、对接邮件发送:
##### 6、对接邮件发送(✅ 已实现)
需要能实现将当前的监测后输出的md文件报告,以邮件的形式发送给czj@huazhaochina.com
##### 7、对接钉钉发送:
\ No newline at end of file
需要能实现将当前的监测后输出的报告,调用钉钉发送给群消息。
参考代码:E:\GithubData\自动化\ubains-module-test\新统一平台\Base\base.py中的dingding_send_message函数来实现
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论