維運熟悉OpenClaw閘道順暢路徑上的日誌,但生產環境會教你退出碼這門詞彙。在2026 年,無論你是在工作室 Mac mini 上自建還是租用雲端執行個體,macOS launchd 包裹 Node 執行階段方式一致:137 多半暗示記憶體壓力,143 常常是一次禮貌的SIGTERM(例如重載),而快速 respawn 往往指向 plist 設定而非模型品質。本文把代碼對應到訊號、示範如何在統一日誌裡篩選而不淹沒在雜訊裡、把症狀關聯回 doctor 閘道診斷,並說明在擴大並行之前何時該先抓活動監視器樣本。
請搭配 LaunchAgent 重啟與復原模式 做乾淨重啟,以及在對話與工具輸出無限膨脹時閱讀 記憶體與上下文裁剪。
退出碼速查
| 碼 | 常見含義 | 首要檢查 |
|---|---|---|
| 0 | 乾淨退出 | 區分有意停止與看門狗 |
| 1 | 通用 Node 錯誤 | 讀 stderr 路徑;前景重跑 |
| 137 | OOM / SIGKILL | 記憶體壓力、工具輸出體量、模型上下文 |
| 143 | SIGTERM | launchd 重載、手動 kill、部署指令稿 |
macOS 也會為圖形應用程式 surface Jetsam 事件;守護行程則更多在統一日誌裡留下原因字串——牢記閘道 bundle id 的拼寫,述詞才能保持狹窄。
在多人共用一台雲端 Mac mini 時,還要區分哪個使用者網域載入了 LaunchAgent:launchctl print gui/$UID/... 與 bootstrap 網域輸出不一致時,看到的退出碼可能來自「你以為已卸載」的舊標籤。
ThrottleInterval 與當機循環
作業以非零退出時,launchd 會退避。若 plist 把 KeepAlive 配得很激進而行程在一秒內當機,維運會看到一面相同時間戳的牆,掩蓋第一條真正的錯誤行。除錯期間可暫時把 ThrottleInterval 提到10 秒,修好根因後再收緊以換取生產回應速度。
文件化 RunAtLoad 是否為 true:常見誤報發生在工程師工作時間手動 unload 了代理,但自動化幾分鐘後又 reload,掩蓋真實觸發條件。
若閘道由 CI 頻繁替換二進位,觀察連續重載是否讓 ThrottleInterval 一直生效——這時 Console 裡會看到 launchd 以固定間隔嘗試拉起,容易誤判為「記憶體洩漏」而非設定抖動。
可讀的 log show 述詞
log show --last 30m --predicate \
'subsystem == "com.apple.xpc.launchd" AND eventMessage CONTAINS[c] "openclaw"'
可再用 process == "launchd" 疊加你的標籤字串。匯出 JSON 方便稽核方在不登入 SSH 的情況下 grep。
對長時間故障,把視窗擴到 --last 24h 並重新導向檔案;統一日誌體積大,務必在筆電冷卻後再打開,以免活動監視器本身搶焦點。
Console.app 工作流程
- 建立名為「閘道退出」的收藏,組合子系統與訊息包含篩選器。
- 復现前先開始串流讀取;當機後立即暫停以免緩衝區捲動遺失。
- 僅在懷疑檔案系統或核心延伸模組時再附加 sysdiagnose——否則保持證據輕量。
記憶體壓力與工具扇出
退出 137 常與並行工具呼叫有關——每次呼叫都可能緩衝數 MB 的 stdout。當主機只有8 GB統一記憶體時,把並行工具限制在三個以下,或把模型上下文視窗降到你在活動監視器記憶體分頁看到的尖峰之下。壓縮記憶體生效時,延遲會先飆升再被殺——把這個當作領先指標。
裁剪策略應與記憶體專文一致:輪替會話紀錄、限制 JSON 深度、在閘道拒絕超大附件而不是讓 Node 先剖析。
若閘道整合了向量檢索或本機嵌入,峰值往往出現在批量索引階段;此時暫時停用無關 skill 或降低批次大小,比盲目調高 Node --max-old-space-size 更安全。
何時取樣 Node 行程
若 CPU 連續兩分鐘以上卡在 100% 且日誌無進展,請在活動監視器擷取樣本並與 plist 版本一併歸檔。樣本能暴露自訂中介軟體裡的緊迴圈,這類問題未必以傳統堆疊形式出現在 stderr。
Plist:KeepAlive、RunAtLoad
僅在零退出真的代表「不健康」時,才在 KeepAlive 下使用 SuccessfulExit。布林值配錯會讓 launchd 重啟本應健康的關機,徒耗雲端 Mac 主機的 CPU 額度。用 launchctl print gui/$UID/your.label 驗證並截圖輸出以便變更管理。
為何 Linux CI 無法復現
CI 容器缺少相同的統一記憶體壓縮、launchd 作業生命週期與鑰匙圈提示。把 Linux 測試當作靜態檢查:閘道建置仍應在 macOS 上冒煙。租用 Mac mini 每天大約16.9 美元即可補上缺口,而不必寄送筆電。
跨境網路環境下,還要注意映像拉取與模型快取路徑是否在 CI 與 macOS 上一致;否則你會在 Linux 上「全綠」,上線後卻被磁碟路徑差異觸發退出碼 1。
復盤模板
- 從最後健康請求 id 到第一條當機日誌的時間線。
- 退出碼、訊號與 launchd 原因字串。
- 記憶體高水位與並行工具數量。
- doctor 輸出雜湊與自上次部署以來的設定 diff。
- 後續動作:程式碼、plist 或容量。
Stderr 輪替與磁碟滿
部分閘道在 StandardErrorPath 無法附加時會以碼 1 退出。macOS 統一日誌會輪替,普通檔案不會。監控 /private/var 與自訂日誌目錄的剩餘空間;多代理共享的 Mac mini 至少保留5 GB餘量。
優先用 newsyslog 或文件化的 logrotate 包裝,而不是無限增長的單檔——在壓力下解析12 GB stderr 尾部往往是二次事故。
部署指令稿中的訊號紀律
藍綠指令稿常送 SIGTERM,等待 15 秒後升級到 SIGKILL。若 Node 捕捉 SIGTERM 以排空 HTTP,但工具呼叫超過寬限期,launchd 仍會記下137——即便維運以為停機很乾淨。延長寬限期或在換二進位前降低在途工具扇出。
公開 /readyz 端點在 SIGTERM 前置為 false,讓負載平衡立即停止傳遞請求——比單獨調 Node 旗標更能減少強殺。
飛行記錄器:最小常駐指標
即便小規模安裝也匯出 process_start_timestamp_seconds、process_exit_code、rss_bytes_max 到 Prometheus。退出碼飆升時,這三條序列能區分記憶體、部署抖動或設定漂移,而不必開啟筆電。
常見問題
137 是否總是 OOM?
閘道上通常如此;仍需對照記憶體曲線。
部署後為何立刻 143?
launchd 在重載時終止舊行程。
stderr 在哪?
查看 LaunchAgent plist 的 StandardErrorPath。
何時租 Mac mini?
當你需要忠實的 launchd 與記憶體行為時。
退出碼考古繁瑣,但比事故分鐘便宜。帶 Apple 晶片的實體 Mac mini 能復現 launchd 退避、記憶體壓縮與檔案描述元預設值——這些都與 Linux 預發布環境不同。MacHTML 提供帶 SSH/VNC 的機器,讓你在發布週末保持在線診斷,週一再關機——彈性容量而不必再開 CapEx 工單。
安靜硬體也有助於你在視訊會議上向分散式團隊朗讀日誌而不被風扇蓋過。
在真實 macOS launchd 上復現 OpenClaw 退出
租用雲端 Mac mini,在升級閘道前驗證退出碼、plist 重載行為與 Console 證據。