From b58f09a9244d4a981c4829a524c72a9476df3662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E7=8A=80=E9=BA=9F?= Date: Sun, 13 Sep 2026 17:48:00 +0800 Subject: [PATCH] =?UTF-8?q?docs(memory):=20Uptime=20Kuma=20=E6=8E=A5?= =?UTF-8?q?=E5=85=A5=20Bark=20=E5=91=8A=E8=AD=A6=E5=B9=B6=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E7=AB=AF=E5=88=B0=E7=AB=AF=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .workbuddy/memory/2026-09-13.md | 1 + .workbuddy/memory/DEPLOY.md | 11 ++++- .workbuddy/tmp/kuma-bark-inspect.sh | 37 ++++++++++++++++ .workbuddy/tmp/kuma-bark-setup.sh | 58 ++++++++++++++++++++++++ .workbuddy/tmp/kuma-bark-src.sh | 12 +++++ .workbuddy/tmp/kuma-bark-verify.sh | 69 +++++++++++++++++++++++++++++ .workbuddy/tmp/kuma-final-check.sh | 19 ++++++++ .workbuddy/tmp/kuma-type.sh | 7 +++ .workbuddy/tmp/kuma-type2.sh | 16 +++++++ 9 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 .workbuddy/tmp/kuma-bark-inspect.sh create mode 100644 .workbuddy/tmp/kuma-bark-setup.sh create mode 100644 .workbuddy/tmp/kuma-bark-src.sh create mode 100644 .workbuddy/tmp/kuma-bark-verify.sh create mode 100644 .workbuddy/tmp/kuma-final-check.sh create mode 100644 .workbuddy/tmp/kuma-type.sh create mode 100644 .workbuddy/tmp/kuma-type2.sh diff --git a/.workbuddy/memory/2026-09-13.md b/.workbuddy/memory/2026-09-13.md index 90f2270..0c33c71 100644 --- a/.workbuddy/memory/2026-09-13.md +++ b/.workbuddy/memory/2026-09-13.md @@ -1,5 +1,6 @@ # 2026-09-13 +2026-09-13 | CHG | Uptime Kuma 接入 Bark 告警:新增通知渠道「Bark 手机推送」(type 必须写 `Bark` 首字母大写,端点用容器网关 `http://172.17.0.1:8081/`),已关联全部 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 | 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 表 + 重启容器」批量添加 diff --git a/.workbuddy/memory/DEPLOY.md b/.workbuddy/memory/DEPLOY.md index 6339587..912b184 100644 --- a/.workbuddy/memory/DEPLOY.md +++ b/.workbuddy/memory/DEPLOY.md @@ -67,5 +67,12 @@ | file / read / tool / sub2api | 120s | 2 | 2000 | | code / status | 300s | 2 | 3000 | - **`service.xpcool.com` 单独放宽为 `["200-399","404"]`**:该后端是纯 POST 接口(遵循本项目"接口全 POST"规范),任何 GET 都 404;返回 404 说明 nginx + GoFrame 存活,**后端进程真挂时 nginx 返回 502,仍会判 DOWN**。 -- **通知渠道(Bark,2026-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/`(或把 kuma 加入 `xpcool-net` 后用容器名 `bark`)。 -- **待办**:「证书到期提前几天通知」需在面板设置里确认。 +- **通知渠道 = Bark(2026-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//`。 + - 挂到监控:`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。 diff --git a/.workbuddy/tmp/kuma-bark-inspect.sh b/.workbuddy/tmp/kuma-bark-inspect.sh new file mode 100644 index 0000000..28ccea6 --- /dev/null +++ b/.workbuddy/tmp/kuma-bark-inspect.sh @@ -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 diff --git a/.workbuddy/tmp/kuma-bark-setup.sh b/.workbuddy/tmp/kuma-bark-setup.sh new file mode 100644 index 0000000..564b13f --- /dev/null +++ b/.workbuddy/tmp/kuma-bark-setup.sh @@ -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" diff --git a/.workbuddy/tmp/kuma-bark-src.sh b/.workbuddy/tmp/kuma-bark-src.sh new file mode 100644 index 0000000..ffa6048 --- /dev/null +++ b/.workbuddy/tmp/kuma-bark-src.sh @@ -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 diff --git a/.workbuddy/tmp/kuma-bark-verify.sh b/.workbuddy/tmp/kuma-bark-verify.sh new file mode 100644 index 0000000..b871bf0 --- /dev/null +++ b/.workbuddy/tmp/kuma-bark-verify.sh @@ -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))s:heartbeat 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" diff --git a/.workbuddy/tmp/kuma-final-check.sh b/.workbuddy/tmp/kuma-final-check.sh new file mode 100644 index 0000000..137bc42 --- /dev/null +++ b/.workbuddy/tmp/kuma-final-check.sh @@ -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;" diff --git a/.workbuddy/tmp/kuma-type.sh b/.workbuddy/tmp/kuma-type.sh new file mode 100644 index 0000000..cb8d011 --- /dev/null +++ b/.workbuddy/tmp/kuma-type.sh @@ -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 diff --git a/.workbuddy/tmp/kuma-type2.sh b/.workbuddy/tmp/kuma-type2.sh new file mode 100644 index 0000000..e6510b0 --- /dev/null +++ b/.workbuddy/tmp/kuma-type2.sh @@ -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