docs(memory): Uptime Kuma 接入 Bark 告警并通过端到端验证

This commit is contained in:
夏犀麟 2026-09-13 17:48:00 +08:00
parent bcfc932061
commit b58f09a924
9 changed files with 228 additions and 2 deletions

View File

@ -1,5 +1,6 @@
# 2026-09-13 # 2026-09-13
2026-09-13 | CHG | Uptime Kuma 接入 Bark 告警新增通知渠道「Bark 手机推送」type 必须写 `Bark` 首字母大写,端点用容器网关 `http://172.17.0.1:8081/<key>`),已关联全部 9 个监控;用临时监控触发真实 DOWN 完成端到端验证Bark 日志实测收到并返 200后清理
2026-09-13 | DEP | 安装用户级技能 `design-taste-frontend`taste-skill v2源 github.com/Leonxlnx/taste-skill上游路径 skills/taste-skill/SKILL.md安装前完成安全审计P2 安全,纯 Markdown 无脚本description 追加中文触发词;来源与审计记录见 `~/.workbuddy/skills/design-taste-frontend/SOURCE.md` 2026-09-13 | DEP | 安装用户级技能 `design-taste-frontend`taste-skill v2源 github.com/Leonxlnx/taste-skill上游路径 skills/taste-skill/SKILL.md安装前完成安全审计P2 安全,纯 Markdown 无脚本description 追加中文触发词;来源与审计记录见 `~/.workbuddy/skills/design-taste-frontend/SOURCE.md`
2026-09-13 | FIX | 本机 git 走系统代理HTTP_PROXY=127.0.0.1:58412导致 github clone 失败Empty reply / CONNECT 502→ 清空代理 env 后用 `curl --noproxy "*"` 拉 codeload tarball 再解压可正常下载;另 Bash 工具在本机不可用shim 报 dirname: command not found需改用 PowerShell 2026-09-13 | FIX | 本机 git 走系统代理HTTP_PROXY=127.0.0.1:58412导致 github clone 失败Empty reply / CONNECT 502→ 清空代理 env 后用 `curl --noproxy "*"` 拉 codeload tarball 再解压可正常下载;另 Bash 工具在本机不可用shim 报 dirname: command not found需改用 PowerShell
2026-09-13 | CHG | Uptime Kuma 第一批监控上线9 个站点 HTTP 监控60/120/300s 三档 + 证书到期通知),因官方 API 不支持创建监控,采用「直写 SQLite monitor 表 + 重启容器」批量添加 2026-09-13 | CHG | Uptime Kuma 第一批监控上线9 个站点 HTTP 监控60/120/300s 三档 + 证书到期通知),因官方 API 不支持创建监控,采用「直写 SQLite monitor 表 + 重启容器」批量添加

View File

@ -67,5 +67,12 @@
| file / read / tool / sub2api | 120s | 2 | 2000 | | file / read / tool / sub2api | 120s | 2 | 2000 |
| code / status | 300s | 2 | 3000 | | code / status | 300s | 2 | 3000 |
- **`service.xpcool.com` 单独放宽为 `["200-399","404"]`**:该后端是纯 POST 接口(遵循本项目"接口全 POST"规范),任何 GET 都 404返回 404 说明 nginx + GoFrame 存活,**后端进程真挂时 nginx 返回 502仍会判 DOWN**。 - **`service.xpcool.com` 单独放宽为 `["200-399","404"]`**:该后端是纯 POST 接口(遵循本项目"接口全 POST"规范),任何 GET 都 404返回 404 说明 nginx + GoFrame 存活,**后端进程真挂时 nginx 返回 502仍会判 DOWN**。
- **通知渠道Bark2026-09-13 勘查结论)**Kuma 2.5.3 **原生支持 Bark**`/app/server/notification-providers/bark.js`),对应 `notification` 表(字段 `id/name/active/user_id/is_default/config``config` 为 JSON 字符串;截至 09-13 该表为空 = 尚未配通知。Bark 服务端 = 容器 `bark``finab/bark-server``0.0.0.0:8081`),另经 `service.xpcool.com/bark/` 反代(末尾斜杠会剥掉 `/bark/` 前缀);当前 server-monitor.sh 用的 key 在 `/etc/server-monitor.conf``BARK_URL`。**注意**Kuma 容器访问 Bark 建议用宿主机地址(容器内 `127.0.0.1` 不是宿主机),即 `http://172.17.0.1:8081/<key>`(或把 kuma 加入 `xpcool-net` 后用容器名 `bark`)。 - **通知渠道 = Bark2026-09-13 已配置并验证)**Kuma 2.5.3 原生支持 Bark`/app/server/notification-providers/bark.js`)。`notification` 表:`id/name/active/user_id/is_default/config`**`config` 是整条通知对象的 JSON 字符串(含 `type`Kuma 用 `providerList[notification.type]` 派发,靠 `item.name` 索引**。
- **待办**:「证书到期提前几天通知」需在面板设置里确认。 - **最大的坑:`type` 必须写 `Bark`(首字母大写)**,不是 `bark`。前端 `NotificationDialog.vue:257` 就是 `Bark: "Bark"`;写成小写则查不到 provider**静默不发通知**。
- 当前配置:`id=1 / name='Bark 手机推送' / is_default=1``config` = `{"type":"Bark","barkEndpoint":"http://172.17.0.1:8081/sm5WnyANWx89GgLtFnRXhk","barkGroup":"Uptime-Kuma","apiVersion":"v1"}`
- **端点必须用容器网关 `172.17.0.1:8081`**kuma 在默认 `bridge` 网络(网关 172.17.0.1),容器内的 `127.0.0.1` 不是宿主机Bark 容器端口发布在宿主机 `0.0.0.0:8081`,故走网关可达(实测 200
- `apiVersion:"v1"` → 走 GET `{endpoint}/{title}/{body}?icon=…&group=…&sound=…`bark-server 支持);不填也默认 v1。Bark key 就是 `/etc/server-monitor.conf``BARK_URL` 那个(`sm5WnyANWx89GgLtFnRXhk`),手机端就是 `https://service.xpcool.com/bark/<key>/`
- 挂到监控:`monitor_notification(monitor_id, notification_id)`**等价于 UI 的 `applyExisting`**。已为 9 个监控全部关联(共 9 行)。
- 脚本:`.workbuddy/tmp/kuma-bark-setup.sh`(幂等写入)、`.workbuddy/tmp/kuma-bark-verify.sh`(端到端验证 + 自清理);改库前必备份 `/tmp/kuma.db.backup.<时间戳>`
- **端到端验证方法(推荐复用)**:临时插一个指向 `http://127.0.0.1:9/` 的监控(`interval=20/retry_interval=20/maxretries=0`)→ 重启容器 → 十几秒即 DOWN 并推送 → 查 `docker logs bark` 确认真的收到 GET 推送200→ 删掉临时监控与其 heartbeat 再重启。全程不清真站点,可靠性最高。
- 全部 9 个监控 `expiry_notification=1`(证书到期通知已开),当前均 UP。

View File

@ -0,0 +1,37 @@
#!/bin/bash
# 1) 确认 Bark key 可用(发一条真实测试推送) 2) 取 Kuma Bark 通知配置字段 3) 查容器网络(决定用哪个地址访问 Bark
# 2026-09-13
KEY="sm5WnyANWx89GgLtFnRXhk"
echo "=== 1. Bark 服务自检 ==="
curl -s -o /dev/null -m 10 -w "healthz=%{http_code}\n" http://127.0.0.1:8081/healthz
echo ""
echo "=== 2. 发送真实测试推送(宿主机 → Bark ==="
curl -s -m 20 -o /tmp/bark-test.json -w "http=%{http_code}\n" \
"http://127.0.0.1:8081/$KEY/Kuma%20Test/ai-verify-20260913"
echo "--- resp ---"
cat /tmp/bark-test.json 2>/dev/null
echo ""
echo ""
echo "=== 3. Kuma 容器网络 ==="
sudo docker inspect uptime-kuma --format '{{json .NetworkSettings.Networks}}'
echo ""
echo "--- 容器内能否访问宿主机 Bark (172.17.0.1) ---"
sudo docker exec uptime-kuma sh -c "curl -s -o /dev/null -m 8 -w 'code=%{http_code}\n' http://172.17.0.1:8081/healthz" 2>&1 || echo "container curl 不可用"
echo ""
echo "=== 4. Bark 通知 provider 源码(取字段名) ==="
sudo docker exec uptime-kuma cat /app/server/notification-providers/bark.js 2>&1 | head -60
echo ""
echo "=== 5. Kuma 表结构 ==="
sudo docker exec uptime-kuma sqlite3 /app/data/kuma.db "PRAGMA table_info(notification);" 2>&1
echo "--- monitor_notification ---"
sudo docker exec uptime-kuma sqlite3 /app/data/kuma.db "PRAGMA table_info(monitor_notification);" 2>&1
echo "--- 现有通知 ---"
sudo docker exec uptime-kuma sqlite3 /app/data/kuma.db "SELECT id,name,active,user_id,is_default FROM notification;" 2>&1
echo "--- 现有监控 ---"
sudo docker exec uptime-kuma sqlite3 /app/data/kuma.db "SELECT id,name FROM monitor ORDER BY id;" 2>&1

View File

@ -0,0 +1,58 @@
#!/bin/bash
# 为 Uptime Kuma 配置 Bark 通知渠道并挂到全部监控2026-09-13
# 幂等:重复执行不会产生重复行
set -e
DB=/app/data/kuma.db
KEY="sm5WnyANWx89GgLtFnRXhk"
KCONF="/data/uptime-kuma/kuma.db"
TS=$(date +%Y%m%d%H%M%S)
echo "=== 0. 备份数据库 ==="
sudo cp "$KCONF" "/tmp/kuma.db.backup.$TS"
ls -l "/tmp/kuma.db.backup.$TS"
echo ""
echo "=== 1. 用 Kuma 的 URL 格式在容器内实测一次(含 icon/group/sound 参数) ==="
sudo docker exec uptime-kuma sh -c "curl -s -o /dev/null -m 15 -w 'kuma_style_url=%{http_code}\n' 'http://172.17.0.1:8081/$KEY/UptimeKuma%20Monitor%20Down/test-from-kuma-container?icon=https%3A%2F%2Fgithub.com%2Flouislam%2Fuptime-kuma%2Fraw%2Fmaster%2Fpublic%2Ficon.png&group=Uptime-Kuma&sound=telegraph'"
echo ""
echo "=== 2. 写入 Bark 通知(若不存在) ==="
NAME='Bark 手机推送'
CONFIG='{"type":"Bark","name":"Bark 手机推送","barkEndpoint":"http://172.17.0.1:8081/sm5WnyANWx89GgLtFnRXhk","barkGroup":"Uptime-Kuma","apiVersion":"v1","isDefault":true,"active":true,"applyExisting":false}'
EXIST=$(sudo docker exec uptime-kuma sqlite3 "$DB" "SELECT COUNT(*) FROM notification WHERE name='$NAME';")
if [ "$EXIST" = "0" ]; then
sudo docker exec uptime-kuma sqlite3 "$DB" "INSERT INTO notification (name, active, user_id, is_default, config) VALUES ('$NAME', 1, 1, 1, '$CONFIG');"
echo "已新增通知渠道"
else
sudo docker exec uptime-kuma sqlite3 "$DB" "UPDATE notification SET active=1, is_default=1, config='$CONFIG' WHERE name='$NAME';"
echo "已更新既有通知渠道"
fi
echo "--- JSON 合法性校验 ---"
sudo docker exec uptime-kuma sqlite3 "$DB" "SELECT id, json_valid(config) AS json_ok, json_extract(config,'\$.type') AS type, json_extract(config,'\$.barkEndpoint') AS endpoint FROM notification;"
NID=$(sudo docker exec uptime-kuma sqlite3 "$DB" "SELECT id FROM notification WHERE name='$NAME' LIMIT 1;")
echo "notification_id=$NID"
echo ""
echo "=== 3. 挂到全部监控(幂等) ==="
sudo docker exec uptime-kuma sqlite3 "$DB" "INSERT INTO monitor_notification (monitor_id, notification_id) SELECT m.id, $NID FROM monitor m WHERE NOT EXISTS (SELECT 1 FROM monitor_notification mn WHERE mn.monitor_id = m.id AND mn.notification_id = $NID);"
echo "--- 关联结果 ---"
sudo docker exec uptime-kuma sqlite3 "$DB" "SELECT mn.monitor_id, m.name, mn.notification_id FROM monitor_notification mn JOIN monitor m ON m.id = mn.monitor_id ORDER BY mn.monitor_id;"
echo ""
echo "=== 4. 重启容器加载配置 ==="
sudo docker restart uptime-kuma > /dev/null
sleep 15
sudo docker ps --filter name=uptime-kuma --format '{{.Names}} | {{.Status}}'
curl -s -o /dev/null -m 10 -w "panel_http=%{http_code}\n" http://127.0.0.1:3001/
echo ""
echo "=== 5. 复核 ==="
sudo docker exec uptime-kuma sqlite3 "$DB" "SELECT id,name,active,is_default FROM notification;"
sudo docker exec uptime-kuma sqlite3 "$DB" "SELECT COUNT(*) AS linked FROM monitor_notification;"
echo "=== 容器日志尾部(看有无通知相关报错) ==="
sudo docker logs --tail 20 uptime-kuma 2>&1 | grep -i -E "error|notification|bark" || echo "(无相关日志)"
echo "DONE"

View File

@ -0,0 +1,12 @@
#!/bin/bash
# 查看 Kuma Bark 通知的完整实现与 config 结构要求
echo "=== bark.js 全文 ==="
sudo docker exec uptime-kuma cat /app/server/notification-providers/bark.js 2>&1
echo ""
echo "=== notification-provider.js 的 postNotification ==="
sudo docker exec uptime-kuma sed -n '1,80p' /app/server/notification-providers/notification-provider.js 2>&1
echo ""
echo "=== notification.js 里 config / type 的解析 ==="
sudo docker exec uptime-kuma grep -n "JSON.parse\|notification.type\|config" /app/server/notification.js 2>&1 | head -30

View File

@ -0,0 +1,69 @@
#!/bin/bash
# 端到端验证 Bark 告警:临时加一个必然失败的监控 → 触发 DOWN → 看推送是否送达 → 清理
# 2026-09-13
DB=/app/data/kuma.db
Q() { sudo docker exec uptime-kuma sqlite3 "$DB" "$1"; }
KCONF=/data/uptime-kuma/kuma.db
TS=$(date +%Y%m%d%H%M%S)
sudo cp "$KCONF" "/tmp/kuma.db.backup.$TS"
echo "=== 1. 新增临时监控(指向必然连不上的端口) ==="
Q "INSERT INTO monitor (name, active, user_id, type, url, interval, retry_interval, maxretries, weight, accepted_statuscodes_json, description) VALUES ('自检 · 临时(验证后自动删除)', 1, 1, 'http', 'http://127.0.0.1:9/', 20, 20, 0, 9999, '[\"200-399\"]', 'Bark 通道端到端验证');"
TMPID=$(Q "SELECT id FROM monitor WHERE name='自检 · 临时(验证后自动删除)' LIMIT 1;")
NID=$(Q "SELECT id FROM notification WHERE name='Bark 手机推送' LIMIT 1;")
echo "temp_monitor_id=$TMPID notification_id=$NID"
Q "INSERT INTO monitor_notification (monitor_id, notification_id) VALUES ($TMPID, $NID);"
echo ""
echo "=== 2. 重启 Kuma 让它加载临时监控并开始探测 ==="
sudo docker restart uptime-kuma > /dev/null
sleep 20
sudo docker ps --filter name=uptime-kuma --format '{{.Names}} | {{.Status}}'
echo ""
echo "=== 3. 等待探测与告警推送(约 60 秒) ==="
for i in 1 2 3 4 5 6; do
sleep 15
ST=$(Q "SELECT status FROM heartbeat WHERE monitor_id=$TMPID ORDER BY id DESC LIMIT 1;" 2>/dev/null)
echo " [${i}] 第 $((i*15))sheartbeat status=${ST:-}"
if [ "$ST" = "0" ]; then break; fi
done
echo ""
echo "=== 4. 该临时监控的心跳记录0=DOWN ==="
Q "SELECT id, status, msg, time FROM heartbeat WHERE monitor_id=$TMPID ORDER BY id DESC LIMIT 5;"
echo ""
echo "=== 5. 通知发送历史 ==="
Q "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%notification%';"
Q "SELECT * FROM notification_sent_history ORDER BY id DESC LIMIT 5;" 2>/dev/null || echo "(无该表或为空)"
echo ""
echo "=== 6. Bark 服务端日志(能看到实际收到的推送) ==="
sudo docker logs --tail 25 bark 2>&1 | tail -25
echo ""
echo "=== 7. Kuma 日志中的通知相关行 ==="
sudo docker logs --tail 60 uptime-kuma 2>&1 | grep -i -E "bark|notification|error" | tail -15 || echo "(无)"
echo ""
echo "=== 8. 清理临时监控 ==="
Q "DELETE FROM heartbeat WHERE monitor_id=$TMPID;"
Q "DELETE FROM monitor_notification WHERE monitor_id=$TMPID;"
Q "DELETE FROM monitor WHERE id=$TMPID;"
echo "--- 清理后剩余监控 ---"
Q "SELECT id, name FROM monitor ORDER BY id;"
echo "--- 清理后关联数(应为 9 ---"
Q "SELECT COUNT(*) FROM monitor_notification;"
echo ""
echo "=== 9. 重启并复核 ==="
sudo docker restart uptime-kuma > /dev/null
sleep 15
sudo docker ps --filter name=uptime-kuma --format '{{.Names}} | {{.Status}}'
curl -s -o /dev/null -m 10 -w "panel_http=%{http_code}\n" http://127.0.0.1:3001/
echo "DONE"

View File

@ -0,0 +1,19 @@
#!/bin/bash
# 复核Bark 通知 + 各监控的证书到期通知开关
DB=/app/data/kuma.db
Q() { sudo docker exec uptime-kuma sqlite3 "$DB" "$1"; }
echo "=== 通知渠道 ==="
Q "SELECT id, name, active, is_default, json_extract(config,'\$.type') AS type, json_extract(config,'\$.barkEndpoint') AS endpoint, json_extract(config,'\$.barkGroup') AS grp FROM notification;"
echo ""
echo "=== 监控 × 证书到期通知开关 ==="
Q "SELECT id, name, expiry_notification, interval, maxretries FROM monitor ORDER BY id;"
echo ""
echo "=== 关联数 ==="
Q "SELECT COUNT(*) FROM monitor_notification;"
echo ""
echo "=== 当前各监控状态(最近一条心跳) ==="
Q "SELECT m.id, m.name, h.status, h.time FROM monitor m LEFT JOIN heartbeat h ON h.id = (SELECT id FROM heartbeat WHERE monitor_id = m.id ORDER BY id DESC LIMIT 1) ORDER BY m.id;"

View File

@ -0,0 +1,7 @@
#!/bin/bash
# 确认 providerList 的 key 命名notification.type 该填什么)
echo "=== providerList 构造 ==="
sudo docker exec uptime-kuma grep -n -B3 -A12 "providerList" /app/server/notification.js 2>&1 | head -50
echo ""
echo "=== providers 列表引入 ==="
sudo docker exec uptime-kuma grep -n -A40 "require(\"./notification-providers" /app/server/notification.js 2>&1 | head -50

View File

@ -0,0 +1,16 @@
#!/bin/bash
# 确认前端提交的 notification.type 到底是 "bark" 还是 "Bark"
echo "=== NotificationDialog 中 type 的来源 ==="
sudo docker exec uptime-kuma ls /app/src/components/notifications/ 2>&1 | head -30
echo ""
echo "=== 搜 bark 类型常量 ==="
sudo docker exec uptime-kuma grep -rn -i "bark" /app/src/components/NotificationDialog.vue /app/src/components/notifications/Bark.vue 2>&1 | head -20
echo ""
echo "=== 搜 type 列表定义notification type 下拉) ==="
sudo docker exec uptime-kuma grep -rn -i "\"bark\"\|'bark'\|value=\"bark\"" /app/src 2>&1 | head -20
echo ""
echo "=== 看 init() 里 providerList 赋值的完整上下文(是否 toLowerCase ==="
sudo docker exec uptime-kuma sed -n '220,245p' /app/server/notification.js 2>&1
echo ""
echo "=== 新增/保存通知时是否校验 type ==="
sudo docker exec uptime-kuma sed -n '275,300p' /app/server/notification.js 2>&1