正确做法是将逻辑封装成独立Shell脚本,用绝对路径调用curl和date(%需转义为\%),通过文件存在性、大小及ERROR/Warning关键字综合判断备份成败,并用markdown格式发送带格式的钉钉消息。

宝塔面板计划任务里怎么调用钉钉 Webhook 发送 MySQL 备份结果
不能直接在宝塔「计划任务」里填一条 curl 命令就完事——因为宝塔计划任务默认不加载用户环境变量,curl 可能找不到,date 的 % 符号不转义会报错,且 JSON 中换行、引号、变量展开极易出错。
正确做法是把逻辑封装成独立 Shell 脚本,用绝对路径调用,并显式指定 /bin/bash 解释器。示例脚本开头必须写:
#!/bin/bash
常见错误现象:date: invalid date ‘+%Y%m%d_%H%M%S’(没转义 %),或 command not found: curl(PATH 不完整),或钉钉返回 "errcode":40044(JSON 格式非法)。
- 所有
date命令里的%必须写成\%,例如$(date +\%Y\%m\%d_\%H\%M\%S) - 脚本中调用
curl时,统一用绝对路径/usr/bin/curl(可用which curl确认) -
msgtype必须是"text"或"markdown",不能拼错;text.text或markdown.text字段值需是单行字符串,含换行要用\n,且整个 JSON 必须合法 - Webhook URL 必须以
https://开头,且包含完整的access_token=xxx参数
备份脚本里如何判断 mysqldump 是否成功并决定是否发钉钉
只靠 mysqldump 命令退出码不够——它即使导出空库或只有表结构,也常返回 0。真正要检查的是备份文件是否存在、大小是否合理、内容是否含 ERROR 或 Warning 关键字。
推荐组合判断:
- 执行
mysqldump后立即用$?检查退出码,非 0 直接报错退出 - 用
stat -c "%s" $BACKUP_FILE 2>/dev/null获取文件字节大小,低于阈值(如1024字节)视为异常 - 用
head -n 50 "$BACKUP_FILE" | grep -q "ERROR\|Warning"扫描头部,命中即告警 - 成功时发绿色 ✅ 消息,失败时发红色 ❌ 并附上错误日志片段(最多 3 行)
别省略重定向:2>&1 | head -n 3 才能捕获真实报错,否则钉钉里只看到“备份失败”四个字,毫无排查价值。
为什么不用宝塔自带的「钉钉告警通知」而要自己写脚本
宝塔面板设置 → 告警通知 → 钉钉,只能响应「面板自身事件」,比如网站宕机、CPU 过载、磁盘满,但它**完全不感知 MySQL 备份任务的执行结果**。你手动点「立即执行」备份,或计划任务跑完,面板不会触发任何告警钩子。
换句话说:那个开关只管「面板健康」,不管「你写的脚本干了啥」。
所以必须绕过它,自己构造 HTTP 请求调用钉钉 Webhook。注意两点:
- 宝塔计划任务的「Shell 脚本」类型,本质就是执行一段 Bash,权限和环境与你 SSH 登录后一致,可放心调用
mysqldump和curl - 如果服务器禁用了外网访问(如防火墙 DROP 了 443),
curl会卡住或超时,建议加-m 10设置 10 秒超时,并在脚本里记录超时日志
钉钉消息里怎么显示带格式的备份详情(时间、大小、数据库名)
用 msgtype: "markdown" 是最稳妥的选择,支持换行、加粗、代码块,且不依赖钉钉客户端版本。关键不是“好看”,而是让信息一眼可扫——比如把文件大小加粗、错误行标红(用 HTML 标签无效,得靠钉钉解析的 markdown 语法)。
示例片段:
{
"msgtype": "markdown",
"markdown": {
"title": "MySQL 备份结果",
"text": "### 数据库备份完成\n- 数据库名:`ybw_pro`\n- 时间:`20260418_010522`\n- 文件大小:**12.4 MB**\n- 路径:`/exec/bak/mysql846/data/daily/ybw_pro_20260418_010522.sql.gz`\n> ✅ 成功"
}
}注意:text 字段值是纯字符串,所有换行必须写成 \n,不能真换行;反引号包裹字段名,双星号加粗数字;最后一行用 > 做引用块,视觉上区隔状态。
最容易被忽略的是:钉钉对 markdown 渲染有长度限制(约 2000 字符),超长会被截断。所以不要 dump 整个 SQL 文件头,也不要拼接太多日志——只放关键元数据 + 最近 3 行错误即可。


















