AI / 自动化 2026年5月21日

租用 Mac mini 上 OpenClaw 閘道 launchd 啟動:node 绝对路径、ProcessType 与退出码 78 修復(2026-05-21)

ProxyMac 工程團隊 2026年5月21日 约 18 分鐘阅读

在 ProxyMac 租用的 Mac mini M4香港、日本、韓國、新加坡、美国节点)上,重啟后 OpenClaw 閘道 LaunchAgent 可能出现:管理端口始终不監聽、launchctl list 显示退出码 78、或冷啟動后 约三分鐘 内 WebSocket 客户端持续收到 1006 异常關閉。本篇 2026 年 5 月 21 日現場手册聚焦 launchd plist 配置错误——ProgramArguments 里裸写 node、缺少 ProcessTypeInteractive——而非 MCP 子程序殘留。可与 閘道 launchctl 重啟恢复無頭 SSH 首次开机清單Node 运行时与 nvm 對齊 對照阅读。

冷啟動:退出码 78、慢監聽与 WebSocket 1006

Apple Silicon 現場反饋里常见两类 launchd 故障形态。立刻退出 78 表示 launchd 未能成功 exec 閘道——多见于 ProgramArgumentsnode 开头,而 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 版本漂移混淆: 若登录 shell 与 plist 下 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 → bootstraplaunchctl print gui/$UID/<label> + plist 原文从 git 恢复旧 plist平台 SRE
任务在跑,重啟后 >60 秒仍无監聽添加 ProcessType Interactive;确认仅一个 label带时间戳的 lsof -nP -iTCP:<port> -sTCP:LISTEN若桌面策略禁止则移除 ProcessType自动化负责人
管理端口双監聽单監聽恢复 操作lsof 中出现两个 PIDbootout 重复 label值班工程师
<30 秒周期崩溃、CPU 高调 ThrottleInterval / KeepAlive——非本文范围log show --predicate 'process == "launchd"' --last 5m还原 throttle 键SRE

九步 plist 修復(ProxyMac mini SSH)

  1. 确认 label: launchctl list | grep -i openclaw,记下完整反向 DNS 名称。
  2. 打印現場状态: launchctl print gui/$(id -u)/<label>,截图最近退出码。
  3. 解析 Node: 同一用户下执行 command -v node,记录绝对路径(常见于 /opt/homebrew~/.nvm)。
  4. 改 plist: ProgramArguments 的 argv[0] 用该路径;閘道入口脚本路径亦用绝对路径。
  5. 加 ProcessType: 若冷啟動延迟符合現場描述,在根字典加入 Interactive。
  6. 校验 XML: 重载前 plutil -lint ~/Library/LaunchAgents/<file>.plist
  7. 回收任务: launchctl bootout gui/$(id -u) <label>bootstrap 同路径(或厂商 kickstart)。
  8. 测到監聽时间:5 秒跑一次 lsof,持续 120 秒;M4 上目标 <15 秒。
  9. 归档: plist 入基础设施仓库;在内部 runbook 链到本文。
ProgramArguments 示例形态: /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 证明亚分鐘级監聽后再推广到生产——区域与套餐见 定價,接入方式见 幫助中心

在 staging 机器上驗證 launchd plist

租用港/日/韩/新/美 Mac mini,夯实 OpenClaw 閘道啟動