租用 Mac mini 上 OpenClaw 閘道 launchd 啟動:node 绝对路径、ProcessType 与退出码 78 修復(2026-05-21)
在 ProxyMac 租用的 Mac mini M4(香港、日本、韓國、新加坡、美国节点)上,重啟后 OpenClaw 閘道 LaunchAgent 可能出现:管理端口始终不監聽、launchctl list 显示退出码 78、或冷啟動后 约三分鐘 内 WebSocket 客户端持续收到 1006 异常關閉。本篇 2026 年 5 月 21 日現場手册聚焦 launchd plist 配置错误——ProgramArguments 里裸写 node、缺少 ProcessType 的 Interactive——而非 MCP 子程序殘留。可与 閘道 launchctl 重啟恢复、無頭 SSH 首次开机清單、Node 运行时与 nvm 對齊 對照阅读。
冷啟動:退出码 78、慢監聽与 WebSocket 1006
Apple Silicon 現場反饋里常见两类 launchd 故障形态。立刻退出 78 表示 launchd 未能成功 exec 閘道——多见于 ProgramArguments 以 node 开头,而 launchd 环境下 PATH 为空或极短。延迟就绪 则表现为 launchctl list 显示任务在跑,但 lsof 数分鐘内看不到監聽;控制台 WebSocket 持续 1006 直到进程终于被排程。二者均不同于 ThrottleInterval 崩溃循环 那种 CPU 飙高、秒级反复拉起。
- 退出状态 78:出现在
launchctl bootstrap或登录后不久——检查~/Library/LaunchAgents/*.plist是否裸写node。 - 180 秒以上:空闲 mini 从开机到首次健康检查成功耗时过长。
- 控制通道 1006:SSH 与磁盘正常却无監聽——多半是端口未起来,而非 TLS 配错。
- SSH 里手动
node gateway.js正常、LaunchAgent 失败——典型 PATH 与绝对路径分裂。
node -v 不一致,先读 运行时對齊。78 是「找不到二进制」;版本错配是「找到了但 ABI 不对」。
launchd 為何不吃 shell PATH,还会压低后台 Agent
LaunchAgent 继承的环境比 Terminal 交互会话瘦得多。文档与社区帖均强调:plist 里的 EnvironmentVariables 无法帮助解析 ProgramArguments 中的解释器名——launchd 先解析可执行文件,再应用环境变量键。因此把笔记本上 argv[0]=node 的 plist 原样拷到無頭 ProxyMac mini,即便 XML 里写了 PATH 仍会失败。
另一方面,缺少 ProcessType 时,macOS 可能把閘道当作后台任务,在重啟后受电源与排程启发式影响。不少維運反饋:在 Label 旁加入 <key>ProcessType</key><string>Interactive</string> 后,冷啟動到監聽可从 约三分鐘 缩到数秒。这是排程衛生,不是长期无人值守开 GUI——一次性 Keychain/TCC 请按 首次开机清單 用 VNC,日常仍走 SSH。
現場处置矩阵(信号 → 首选动作)
| 主要信号 | 首选响应(顺序重要) | 应留存证据 | 误操作回滚 | 负责人 |
|---|---|---|---|---|
| OpenClaw 标签最近退出码 78 | 将 argv[0] 改为 $(command -v node) 绝对路径;bootout → bootstrap | launchctl print gui/$UID/<label> + plist 原文 | 从 git 恢复旧 plist | 平台 SRE |
| 任务在跑,重啟后 >60 秒仍无監聽 | 添加 ProcessType Interactive;确认仅一个 label | 带时间戳的 lsof -nP -iTCP:<port> -sTCP:LISTEN | 若桌面策略禁止则移除 ProcessType | 自动化负责人 |
| 管理端口双監聽 | 按 单監聽恢复 操作 | lsof 中出现两个 PID | bootout 重复 label | 值班工程师 |
| <30 秒周期崩溃、CPU 高 | 调 ThrottleInterval / KeepAlive——非本文范围 | log show --predicate 'process == "launchd"' --last 5m | 还原 throttle 键 | SRE |
九步 plist 修復(ProxyMac mini SSH)
- 确认 label:
launchctl list | grep -i openclaw,记下完整反向 DNS 名称。 - 打印現場状态:
launchctl print gui/$(id -u)/<label>,截图最近退出码。 - 解析 Node: 同一用户下执行
command -v node,记录绝对路径(常见于/opt/homebrew或~/.nvm)。 - 改 plist:
ProgramArguments的 argv[0] 用该路径;閘道入口脚本路径亦用绝对路径。 - 加 ProcessType: 若冷啟動延迟符合現場描述,在根字典加入 Interactive。
- 校验 XML: 重载前
plutil -lint ~/Library/LaunchAgents/<file>.plist。 - 回收任务:
launchctl bootout gui/$(id -u) <label>再bootstrap同路径(或厂商 kickstart)。 - 测到監聽时间: 每 5 秒跑一次
lsof,持续 120 秒;M4 上目标 <15 秒。 - 归档: plist 入基础设施仓库;在内部 runbook 链到本文。
/opt/homebrew/bin/node + openclaw-gateway 入口脚本的绝对路径 + --config + 配置 JSON 绝对路径——除非设置 WorkingDirectory,勿在包装脚本里依赖 cd。
驗證監聽、健康检查与 WebSocket 稳定
bootstrap 后确认配置的管理端口(維運文档常举 18999,以你的 config.json 为准)仅一个 PID 在 LISTEN。若启用 HTTP 健康路由则 curl 探测;再连桌面客户端,重啟后 30 秒内不应再出现 1006。健康正常但 MCP 工具异常时,转读 MCP 殘留衛生,勿反复改閘道 plist。
自动化主机建议每季度做一次真重啟:launchd 回归常出现在 macOS 安全更新之后,而非当日 SSH 改 plist 时。工单里请同时记录 uname -r 与到監聽耗时。
預防:plist 基础设施化与 staging 标签隔离
- plist 进 git,Node 绝对路径由镜像构建模板注入(Homebrew 前缀或 nvm 默认)。
- dev/staging/prod 使用不同 LaunchAgent label,避免端口冲突——见重啟恢复文。
- CI 冒烟: 部署后用 SSH 脚本断言 <20 秒出现監聽再标健康。
- 在 HK/JP/KR/SG/US 备 disposable 实验机 调 plist,比在產線編排器上试错便宜。
常見問題
为什么 LaunchAgent 一啟動就退出码 78? launchd 先解析 ProgramArguments 再应用 EnvironmentVariables;裸写 node 在空 PATH 下会失败。请改为 command -v node 的绝对路径,再 bootout 并 bootstrap。
为什么重啟后要几分鐘才監聽? 默认 plist 常缺 ProcessType Interactive,系统会把后台啟動降优先级。在根字典加入 Interactive 后,许多 Apple Silicon mini 可从约三分鐘降到数秒。
与 ThrottleInterval 崩溃循环有何不同? 后者是 CPU 高、秒级反复拉起。78 是閘道未运行前的配置错误。无崩溃风暴却长时间无監聽,应查 ProcessType 或排程,而非 KeepAlive 与错误二进制死循环。
為何在租用 Mac mini 上夯实 OpenClaw launchd
閘道 plist 属于基础设施:必须扛住重啟、系统升级,以及只熟悉笔记本 Homebrew 路径的同事。Apple Silicon M4 冷啟動时序可预期,macOS launchd 与 OpenClaw 官方 LaunchAgent 流程一致,HK / JP / KR / SG / US 节点让控制面更贴近你已对接的 API 区域。ProxyMac 支持在 staging mini 克隆已驗證 plist,SSH 证明亚分鐘级監聽后再推广到生产——区域与套餐见 定價,接入方式见 幫助中心。