Uptime Kuma Agent自动批量配监控服务:内部 Socket.IO API 四脚本工具箱,与它踩过的所有坑

发布:2026-10-23 | 实测窗口:2026-10-18(Uptime Kuma 2.5.6 容器源码逐条核验)
结论先行:Uptime Kuma 没有管理型 REST API,Settings → API Keys 生成的密钥只服务 /metrics——想批量加监控、配 SMTP 告警、开公开状态页,唯一路径是内部 Socket.IO API。本工具箱用四个零安装脚本把这条路径固化成"管道即用":幂等可重跑、凭据只走 stdin(不打印、不落盘)、在容器内跑(复用自带 socket.io-client,本机一个包都不用装)。
GitHub 仓库:【待补充:仓库地址】(首发 commit 后回填)


一、为什么会有这个工具箱

Uptime Kuma 是最流行的自托管监控面板之一,但当你想"程序化地管理它"时会撞上一堵墙:

  1. 没有管理型 REST API。Internal-API Wiki 自己声明:内部 Socket.IO API 非官方支持、大版本升级可能破坏性变更。
  2. API Key 是个陷阱。Settings → API Keys 生成的 uk2_... 密钥只服务于 /metrics(Prometheus 抓取),拿它去跑管理操作一律失败(Prometheus API Keys Wiki 为出处)。网上不少教程把这两件事混为一谈,照做会白折腾半天。
  3. UI 批量操作靠手点。几十个监控、SMTP 通知挂全量、状态页分组——点到手酸,且不可复现。

所以答案只剩一个:账号密码登录 + 内部 Socket.IO API。本工具箱把 2026-10-18 两套生产实例的实操抽离泛化成四个脚本,所有踩坑都固化进了代码与文档。

⚠️ 与文档冲突时以容器源码实测为准——本工具箱全部事件与载荷形状在 louislam/uptime-kuma:2.5.6 源码逐条核验过。


二、四脚本清单(stdin 协议一句话版)

脚本 干什么 stdin 组成
uptime-kuma-add-monitors.js 批量加 HTTP 监控(幂等:按名称/URL 查重) 1 用户名 / 2 密码 / 3 行起到 EOF:监控清单 JSON(可多行 pretty)
uptime-kuma-email-notify.js SMTP 告警:先测后存 + applyExisting 全量挂载 1 用户名 / 2 密码 / 3 单行邮件载荷 JSON / 4(可选)旧通知名
uptime-kuma-status-page.js 公开状态页 upsert(分组动态收录全部监控) 1 用户名 / 2 密码 / 3 行起到 EOF:状态页配置 JSON
drop-notification.js 删指定通知 + 全监控关联验收 1 用户名 / 2 密码;通知 id 走命令行参数

共同设计:

  • 零安装:docker cp 脚本进容器 /app/ 下执行,node 从脚本目录向上找到容器自带的 socket.io-client——本机不需要 npm install 任何东西。
  • 幂等:监控按名称/URL 查重,通知与状态页 upsert——重复执行不产生副本。
  • 自适配:全新未初始化实例自动 setup 创建账号后继续。
  • 凭据纪律:用户名/密码/SMTP 授权码只经 stdin 进入进程内存,脚本不打印、不写盘;输出里邮箱打码(maskEmail)、密码永不回显。

三、五个踩坑(每个都是真实事故/实测换来的)

坑 1:notificationList 必须在 login 之前订阅 ⚠️ 最贵的一个

服务端在 login ack 的处理过程中就推送 notificationList。如果 login 成功后再 socket.on("notificationList"),会读到 0 条 → 旧通知名匹配失效 → 新建出第二个通知 → 同一故障发两封邮件(生产真实事故)。修复就一行:订阅写在 emit("login") 之前。

// ⚠️ 必须在 login 之前订阅(2026-10-18 生产实测踩坑):
let notifList = null;
socket.on("notificationList", (list) => { notifList = list; });
await loginWithSetup(socket, username, password);   // 订阅在前,登录在后

drop-notification.js 的 monitorList 订阅同理。

坑 2:API Key 配不了监控(见 §一第 2 条)

uk2_... 只服务 /metrics。管理操作一律账号密码登录——这不是脚本的限制,是 Uptime Kuma 的设计边界。

坑 3:测试信的 Liquid 变量是 dummy 值

testNotification 发出的测试信里,{{ name }} 是 "Monitor Name not available"、{{ status }} 是 ⚠️ Test、heartbeatJSON 是 null。直接用真实告警模板会得到一个错乱的测试主题。样例载荷里的这个分支是刻意的:

{% if name == "Monitor Name not available" %}{{ msg }}{% else %}{{ status }} - {{ name }}{% endif %}

测试信与真实告警的主题都正确。配套纪律:邮件载荷必须是单行 JSON(email 脚本只读 stdin 第 3 行;PowerShell 用 ConvertTo-Json -Compress,bash 用 jq -c)——别把样例"美化"成多行。

坑 4:载荷字段类型差一个字符就崩

  • add 的载荷必须含 accepted_statuscodes 数组,否则服务端处理器直接抛错;
  • saveStatusPage 的 config.domainNameList 必须是数组(空数组也行,字符串必崩);
  • 分组形状固定 {name, monitorList:[{id}]}。

监控默认值与前端 EditMonitor.vue 实发口径对齐:60s 间隔 / 200-299 判活 / maxretries 0——对着前端开发者工具抄一遍口径,比猜文档准。

坑 5:脚本放错目录 → Cannot find module 'socket.io-client'

node 从脚本所在目录逐级向上找 node_modules。正式用法是 docker cp 到容器 /app/ 下;放 /tmp 临时调试必须加 -e NODE_PATH=/app/node_modules。另外容器冷启动后数秒内首次登录可能慢于 15s 应答窗口——复跑即可,不是 bug。


四、部署与使用流程(推荐路径)

整条链路的推荐形态是 “本地 Docker 验证 → 服务器部署 → 本地自动批量添加”:

① 本地 Docker 起一个 Uptime Kuma 测试实例
        ↓  按仓库 README 用假凭据/测试凭据跑通四脚本全流程
② 验收 OK(监控首跳 UP / 测试信收件 / 状态页免登录可开)
        ↓  用户在服务器上部署正式 Uptime Kuma
③ 拿到账号密码(注意:只能是账号密码,API Key 走不通,见坑 2)
        ↓
④ 本地直接自动批量添加要追踪的服务(远程执行模式,免 SSH)

远程执行模式——本机容器当执行器,一条环境变量指向目标实例:

"$u`n$pw`n$cfgJson" | docker exec -i -e UPTIME_KUMA_URL=http://<目标IP>:<端口> `
  <本机执行容器> node /app/uptime-kuma-add-monitors.js

最短上手(本地容器):

# 0) 四个脚本进容器
for f in scripts/*.js; do docker cp "$f" <容器名>:/app/; done

# 1) 凭据文件(裸两行:第1行用户名、第2行密码;用后即删)
printf '%s\n%s\n' '<用户名>' '<密码>' > creds.txt

# 2) 批量加监控
{ cat creds.txt; cat examples/targets.sample.json; } | \
  docker exec -i <容器名> node /app/uptime-kuma-add-monitors.js

# 3) 用完删凭据
shred -u creds.txt 2>/dev/null || rm -f creds.txt

验收清单:监控列表出现全部目标且首跳 UP / 收件箱有测试信 / 状态页 URL 无痕窗口可开。


五、安全设计(代码层保证,不是靠自觉)

保证 实现
凭据不落盘 四脚本零 writeFile;凭据只经 stdin → 进程内存 → socket 发往你自己指定的 UPTIME_KUMA_URL(默认 localhost:3001)
零外呼 全仓库唯一的 fetch 是状态页公开验收接口(拉自己刚建的 /api/status-page/<slug>);零 telemetry、零第三方域名
不回显 password 只出现在 login/setup 发送处,无一处进 console.log;邮箱输出 maskEmail 打码
仓库不收凭据 .gitignore 挡 creds.txt / key.txt / *.key / *.pem / *.log;所有 example 均为占位符形态
AI 协作红线 仓库内置 AGENTS.md:冒烟只许假凭据、commit 信息不得含真实地址账号邮箱、发现疑似问题先问不自行改码

请勿把凭据文件内容粘贴给 AI 或贴进聊天——工具箱所有 sample 都是占位符,没有例外。


六、给 AI Agent 用的仓库(顺带一提)

本仓库自带 AGENTS.md,AI 编码代理打开仓库即自动获得:stdin 协议表、五条红线(login 前订阅、单行载荷、Liquid if 分支、数组口径、先问再改)、验证口径(node --check 四脚本 + 假凭据冒烟)。也就是说——把仓库丢给任何一个支持 AGENTS.md 的 agent,它就能正确地替你跑这四条管道,而不会"好心"把该保留的坑修掉。


七、事件速查表(2.5.6 源码核验,排障用)

事件 要点
login / needSetup / setup 认证;全新实例自动 setup(密码太弱报 passwordTooWeak)
getMonitorList → monitorList 事件 列表靠事件推送,ack 只回 {ok}
add 载荷须含 accepted_statuscodes 数组,否则处理器抛错
addNotification(payload, id, cb) id=null 新建 / 有 id 更新;applyExisting:true 挂全量
notificationList 事件 ⚠️ login ack 处理中就推送——必须 login 前订阅,否则读 0 → 双通知双邮件
getStatusPage / addStatusPage / saveStatusPage 分组 {name, monitorList:[{id}]};config.domainNameList 必须是数组

排障 Top 5:

症状 原因 / 处置
登录失败:用户名或密码错误 凭据文件须裸两行(有标签行会错位);或密码错
监控清单 JSON 解析失败 第 3 行起不是合法 JSON / creds 混入多余行
测试邮件发送失败:Invalid login... SMTP 授权码(非登录密码)错/过期 → 服务商后台重新生成
测试信里 name 显示 dummy 值 正常——renderTemplate 测试态兜底,用样例 if 分支规避
Cannot find module 'socket.io-client' 脚本不在容器 /app 下 → 重新 docker cp;临时位置加 -e NODE_PATH=/app/node_modules

八、脱敏声明

  • 全文无真实服务器地址、账号、密码、SMTP 授权码、收件邮箱;示例一律 <目标IP>:<端口>、<用户名> 占位符形态。
  • 工具箱仓库内所有 example 均为占位符;.gitignore 挡凭据类文件。
  • 本工具箱生成链路零外部请求(唯一 fetch 为自建状态页公开接口);文中外部链接仅为 Uptime Kuma 官方 wiki 出处。
  • 叙事中的"生产事故""实测"仅保留日期与现象,不含可定位到具体环境的设备/网段/规模信息。

附:仓库与出处