兰 亭 墨 苑
期货 · 量化 · AI · 终身学习
首页
归档
编辑文章
标题 *
URL 别名 *
内容 *
(支持 Markdown 格式)
# 深夜运维实录:从 dsh.want.biz 失联到三个 AI 同仓打工 > 记录 2026 年 9 月初的一个深夜排障:一条 Cloudflare Tunnel 的静默失联,牵出一段 2024 年就埋下的守护失效;随后顺藤摸瓜研究了智谱 ZCode 的 CLI 与计费通道机制;最后发现自家仓库里,三个 AI 正在同一条 git 工作区里并行打工。 ## 一、dsh.want.biz 打不开了 一切从一句"本机 cloudflare 是不是连不上了,dsh.want.biz 打不开了"开始。 排查的第一步永远是把链路拆开看。dsh.want.biz 的链路是:**浏览器 → Cloudflare 边缘(Access 认证)→ Cloudflare Tunnel → 本机 3080 端口**。逐段验证后发现一个反直觉的现象: - `curl https://dsh.want.biz` 返回 302,跳转到 Cloudflare Access 登录页——边缘、DNS、认证全部正常; - 本机 `127.0.0.1:3080` 返回 200——源站服务正常; - 但 `ps aux | grep cloudflared` —— **进程不存在**。 Cloudflare Access 的登录跳转发生在边缘,不需要源站在线。所以"302 能通"完全可能是假象:登录之后的请求要经隧道回源,隧道断了,用户看到的就是打不开。 `cloudflared tunnel info` 一锤定音:`MacMini_home` 隧道的 CONNECTIONS 列是空的——隧道离线。而同一账号下 NAS 的隧道有 4 个连接在线。 ## 二、根因:一次自动更新 + 一段两年前的历史遗留 翻日志(`~/.cloudflared/nohup.out`),死因写得明明白白: ``` ERR Initiating shutdown error="cloudflared has been updated to version 2026.8.3" ``` cloudflared 自动更新到新版后**自行退出**,时间凌晨 02:13。这本不该是致命的——launchd 守护本该在几秒内把它拉起来。但翻开 `~/Library/LaunchAgents/com.cloudflared.tunnel.plist`,发现了真正的深坑: 这个 plist 在 **2024 年 5 月**就被替换成了一段 60 字节的 bash 脚本内容(`nohup cloudflared tunnel run &`),原始 plist 被改存为 `.plist.save`。launchd 根本无法加载一个不是 XML 的 plist。也就是说,近一年多来 cloudflared 一直是 `nohup` 裸跑的,进程一死就无人拉起,静默失联。 **两层故障叠加:直接死因是自动更新退出,深层死因是守护层早已名存实亡。** ## 三、修复:升级为系统级 LaunchDaemon 应急很简单:手动重启隧道,连接器重新注册到边缘。根治才是正戏——把守护从用户域迁到系统域(LaunchDaemon,root 运行,开机即跑,不依赖用户登录): ```xml <!-- /Library/LaunchDaemons/com.cloudflared.tunnel.plist 关键设计 --> <key>ProgramArguments</key> <string>/opt/homebrew/bin/cloudflared</string> <string>tunnel</string> <string>--config</string> <string>/Users/ygs/.cloudflared/config.yml</string> <string>run</string> <key>KeepAlive</key><true/> <key>ThrottleInterval</key><integer>10</integer> ``` 三个关键设计: 1. **显式 `--config`**:root 用户的 HOME 在 `/var/root`,不指定路径就找不到 ingress 配置(`dsh.want.biz → http://127.0.0.1:3080` 的映射); 2. **`KeepAlive=true`**:针对"自动更新后退出"这个根因的自愈——进程退出 10 秒内 launchd 自动重拉; 3. **系统域**:LaunchDaemon 归 root,Mac 重启后无需登录即恢复。 验证自愈能力的方法很暴力:手动 `kill` 掉进程,14 秒后观察——launchd 自动拉起新进程,隧道重新注册。完事。 顺带清了两处历史遗留:一个 token 指向早已删除隧道的死配置 plist(归档为 `.disabled-oldtoken`),以及用户域那个被改坏的 plist(退役为 `.userdomain-retired`)。 **经验**:macOS 上任何"应该常驻"的进程,用 nohup 裸跑都是定时炸弹。launchd 的 LaunchDaemon + KeepAlive 才是正解;写进 plist 的必须是二进制本身而不是包一层 bash 脚本,否则 KeepAlive 盯的是秒退的脚本,毫无守护意义。 ## 四、插曲:ZCode 研究与一次"忍住" 排障间隙研究了下智谱的 ZCode(GLM 系的编程 Agent)。两个发现: **其一,zcode-cli 还没正式发布。** npm 包已占位(0.0.1),但 `--help` 里自己写着 "This package name is reserved. The full CLI is under active development.",唯一的 `chat` 命令标注 coming soon。完整能力目前仍锁在桌面 App 里。 **其二,"夜间免费"的判定机制藏在配置文件里。** ZCode 的 `config.json` 按 provider 组织渠道,每个渠道独立的 baseURL 就是计费分流点: - `zcode.z.ai/api/v1/zcode-plan/anthropic` —— ZCode 专属通道(夜间 23:00–次日 9:00 用 GLM-5.3-Flash 额度消耗为 0) - `open.bigmodel.cn/api/anthropic` —— 普通 Coding Plan 通道(同期额度 ×2) 判定三要素:**请求打到哪个 baseURL + 账号订阅资格(服务端 entitlement,配置里那句 `coding_plan_not_entitled` 就是证据)+ 时间窗口**。三项满足自动免单——这也解释了免费额度为何"锁死在 ZCode 里导不出来"。 至于"把 ZCode 的通道提取出来配到其他工具蹭免费"这个念头,认真评估后放弃了:凭证就在本地配置里,技术上五分钟就能配,但服务端大概率校验客户端特征,社区已有 Coding Plan 风控封号的先例。**为两周的限时活动押上付费主账号,期望值是负的。** 夜间 ×2 的官方补偿已经够用——识别哪些便宜不能占,也是运维素养的一部分。 ## 五、意外的惊喜:三个 AI 在同一仓库里打工 检查 ZCode 交付时,git 工作区给了个大惊喜——除了 10 章书稿,还有 16 个文件、694 行的代码改动。一度以为是工具越界,对质之后发现真相更有趣: - **ZCode** 在写《GLM突围记》(智谱编年史书稿):BRIEF → 大纲 → 素材库 → 逐章 8000–10000 字,先冲刺后精修; - **dsh**(自研 Harness)在做 repl 功能开发:`/rename` 会话命名命令、doctor 自检、剪贴板图片等一整套——设计提案来自 Gemini; - **Ubuntu-R86S** 上的文件监控助手持续推送变更通知,成了两个 Agent 的"心电图"——通知还在来,就说明都活着。 三个模型、一台 Mac、同一条 git 工作区,各司其职。两个实践心得: 1. **双 Agent 并行前先提交一次**。工作区是共享的,开工前各自的基线干净,出事才能秒判"谁的改动"——否则只能靠文件 mtime 考古。 2. **Agent 的实现笔记值得读**。`.agents/notes/` 里的功能笔记带着 "Alternatives considered"——为什么拒绝伪造附件引用、为什么拒绝传文件路径代替图片块。这些"不做什么"的记录,比"做了什么"更有长期价值。 ## 六、写在最后 这一晚的完整链路:**一条失联的隧道 → 一段埋了两年多的坏配置 → 一次守护架构升级 → 一场 ZCode 机制侦察 → 一次"忍住不蹭"的决策 → 三个 AI 的同仓协作**。 运维的乐趣大抵如此:每一个"打不开了"的背后,都藏着一串值得刨到底的为什么。 --- *标签:运维, cloudflare-tunnel, launchd, macOS, ZCode, AI-Agent, 多智能体协作*
配图 (可多选)
选择新图片文件或拖拽到此处
标签
更新文章
删除文章