0.0.0.0 裸奔或 SSH 隧道與實際監聽不一致)、令牌(未輪替、寫進可讀 plist/日誌)、更新策略(全域 npm 升級後 launchd 仍指向舊二進位)。下文用 HowTo 順序收斂到 LaunchAgent、巡檢腳本與最小排錯;延伸請讀閘道安全加固、ClawHub 與 CI 依賴預拉取、CI 預拉取版本一致。當閘道穩定後,才能把「模型/套件拉取」與流水線旁路自動化接到同一節點而不被隨機重啟打斷——這正是 MacPull 用戶在跨境拉取與 CI 場景裡最在意的可預期執行面。
- 綁定:生產優先
127.0.0.1;遠端調用走 SSH-R/內網代理,避免無 ACL 的公網監聽。 - 令牌:環境變數或祕鑰檔注入;輪替時同步 plist 與 CI Variables。
- 更新:固定維護窗口;升級後跑
openclaw doctor與健康探針,保留回滾路徑。
前置條件與環境變數
先鎖定「誰在跑、讀哪份設定」,守護程序才不會因登入/非登入 session 差異而漂移。
Node 基線:對齊官方文件(建議 Node 24,相容下限 22.16+ LTS)。執行 node -v 並與 CI 映像一致。
設定根目錄:需要多環境隔離時設定 OPENCLAW_HOME 或 OPENCLAW_CONFIG_PATH,並在 Runbook 寫死路徑;目錄權限建議 700。
網路與代理:若節點走企業代理,將 HTTPS_PROXY/NO_PROXY 同時寫入互動 shell 與 plist 的 EnvironmentVariables,避免「手動起服可用、launchd 起服失敗」。
# 互動式驗證(與 plist 內環境應一致) printenv | egrep 'OPENCLAW|HTTPS_PROXY|NO_PROXY'
閘道啟動與綁定策略
HowTo 主線:先以手動前景啟動確認行為,再交給 LaunchAgent;健康檢查應與實際鑑權方式一致(例如 Bearer Token)。
手動驗證:在專用帳號下執行官方建議的 gateway 啟動命令,確認日誌無 EADDRINUSE/權限錯誤。
綁定:將 listen 設為 127.0.0.1;用 lsof -nP -iTCP -sTCP:LISTEN 核對位址欄位不是 *。
探針:以 curl 命中文件中的 health 路徑;HTTP 200 且延遲穩定後再裝守護程序。埠號、標頭名稱請替換為你的實際值。
curl -sS -o /dev/null -w 'http_code=%{http_code} time=%{time_total}\n' \
-H 'Authorization: Bearer YOUR_TOKEN' \
http://127.0.0.1:PORT/health
與 CI 銜接時,讓流水線在編譯前呼叫同一探針或 openclaw status,可把「閘道掛了卻仍跑依賴步驟」的浪費時間壓掉;細節可對照站內 ClawHub/預拉取文章中的技能編排。
巡檢腳本模板(LaunchAgent 守護程序)
推薦先跑 openclaw onboard --install-daemon 產生官方 plist,再按需加上日誌路徑與環境變數。若自管 plist,請至少包含:ProgramArguments、WorkingDirectory、KeepAlive、StandardOutPath/StandardErrorPath。
# 載入使用者 LaunchAgent(路徑與 label 依實際修改) launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.openclaw.gateway.plist launchctl kickstart -k gui/$(id -u)/com.example.openclaw.gateway
下列 Bash 模板可做定時巡檢(另建一個 com.example.openclaw.patrol.plist 以 StartInterval 每 5 分鐘執行,或用 cron;關鍵是與閘道同一使用者)。腳本非 0 退出即發告警。
#!/usr/bin/env bash
set -euo pipefail
PORT="${OPENCLAW_GATEWAY_PORT:-18789}"
TOKEN="${OPENCLAW_GATEWAY_TOKEN:?missing token}"
code=$(curl -sS -o /dev/null -w '%{http_code}' -H "Authorization: Bearer ${TOKEN}" \
"http://127.0.0.1:${PORT}/health" || true)
[[ "$code" == "200" ]] || { echo "health_fail http=$code"; exit 2; }
openclaw status >/dev/null || { echo "openclaw_status_fail"; exit 3; }
df -h / | awk 'NR==2 {gsub(/%/,"",$5); if ($5+0>90) exit 4}'
exit 0
launchctl print gui/$(id -u)/LABEL看上次退出碼與環境變數是否載入。- 讀取 plist 指定的 StandardErrorPath;沒有則用
log show --predicate 'process == "node"' --last 20m收斂時段。 - 確認健康檢查與實際進程埠一致;改埠後忘記改巡檢是常見假陽性。
常見報錯 FAQ
| 現象 | 高概率原因 | 處置(可複現) |
|---|---|---|
ECONNREFUSED | 守護未起、錯埠、或只綁 IPv6 | launchctl list | grep -i openclaw;lsof -i :PORT;必要時用 curl -g 測 ::1 |
| 健康 401/403 | Token 與閘道配置不一致、輪替未同步 | 比對 plist 與 shell 的 Authorization;grep 舊 token 是否仍留在 CI |
EACCES 寫日誌/設定 | WorkingDirectory 屬主錯誤 | chown -R svcuser:staff /path/to/workspace;修正 StandardOutPath 目錄可寫 |
| 升級後立刻崩潰 | npm prefix 變更、全域連結斷裂 | which openclaw;在 plist 使用絕對路徑;備份上一版並回滾驗證 |