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 网关启动