先把三條維運原則記進肌肉記憶,再讀正文:
-
探針雙驗,I/O 不誤判
curl 探 18789 之前先用 lsof 確認埠歸屬;Dashboard 卡頓先查磁碟 I/O,不要把寫日誌高峰誤讀成閘道故障。
curl + lsof
-
灰度升級,30 分鐘回滾窗口
凍結版本號 → 黃金樣機先行 → 再滾生產;tarball 備份與舊 plist 路徑同時還原,回滾不超過 30 分鐘。
≤ 30 分鐘
-
日誌與根磁碟分離
日誌目錄與 npm 快取獨立掛載或獨立 logrotate 輪轉,防止靜默寫滿根磁碟導致 Gateway 異常退出。
logrotate 7d
本篇只回答一個問題
OpenClaw 安裝腳本跑完、Gateway 18789 首次亮起綠燈之後,團隊往往進入「跑著跑著出問題、出了問題沒有 Runbook」的階段:閘道偶爾 401、升級後某台行為不一致、日誌把根磁碟寫滿導致 Gateway 靜默退出。這些都不是安裝文件要解決的問題。
本篇只回答一個問題:如何把 OpenClaw 的日常維運動作標準化成一份可以複用的 Runbook,讓任何一位團隊成員接手都能在 15 分鐘內完成巡檢或回滾?涵蓋範圍:Gateway 健康巡檢 → 灰度升級策略 → 回滾流程 → Tailscale / SSH 傳輸選擇 → 日誌磁碟規劃。
1. Gateway 18789 健康巡檢
很多團隊的「巡檢」只有一條 curl,這不夠。Gateway 在埠被佔用或 launchd 未正確拉起時,curl 會掛起而不是立即失敗。標準巡檢要同時跑 curl 和 lsof,分別驗證回應與埠歸屬。
# 1. HTTP 探活:期望 200,輸出 fail 則警報 curl -fsS --max-time 3 http://127.0.0.1:18789/health \ && echo "gateway OK" || echo "GATEWAY FAIL" # 2. 埠歸屬確認:pid 應屬 node/openclaw 程序 lsof -nP -iTCP:18789 -sTCP:LISTEN # 3. 最近 50 行錯誤日誌(路徑按實際安裝目錄) tail -n 50 ~/.openclaw/logs/gateway.log | grep -i "error\|warn\|exit"
如果 curl 回傳 200 但 Dashboard 仍然卡頓,優先排查磁碟 I/O:iostat -d 1 5 看寫入峰值。把日誌寫入高峰誤判為閘道故障是最常見的假警報來源。固定一台「黃金樣機」與生產保持同版本,出現異常時可以快速對照。
lsof -iTCP:18789 回傳的 pid 不是 OpenClaw 程序,先用 launchctl list | grep openclaw 確認服務狀態,再確認是否有殘留舊版本程序沒有被 bootout 清理乾淨。直接 kill 佔用程序而不清理 plist,會導致 launchd 在下次登入時重新拉起。
2. 升級前三件事:版本凍結、黃金樣機與磁碟餘量檢查
OpenClaw 的版本迭代頻率較高,不加節制地跟隨最新版本會帶來兩類風險:設定鍵變更導致 Gateway 啟動失敗,以及新版本與已有 Channel 設定不相容。灰度升級是標準做法,但很多團隊把「灰度」理解成「先升一台看看」,忽略了升級前的版本凍結和磁碟餘量檢查。
| 檢查項 | 做了 標準灰度流程 | 沒做 直接 npm update |
|---|---|---|
| 版本凍結(記錄目前 tag) | 回滾時直接 npm install openclaw@舊tag |
不知道舊版本號,只能 tarball 恢復 |
| 黃金樣機先行 | 異常隔離在測試節點,生產不受影響 | 全量失敗,所有通道同時斷線 |
| 根磁碟餘量 ≥15% | npm install 的暫存檔案有足夠空間 | 安裝途中寫滿磁碟,留下半殘狀態 |
# 記錄目前版本
npm list -g openclaw --depth=0 > .upgrade-memo
# 封存目前設定
tar czf openclaw-config-$(date +%Y%m%d).tar.gz \
~/.openclaw/config/ \
~/Library/LaunchAgents/com.openclaw.gateway.plist
# 確認磁碟餘量 ≥15%
df -h / | awk 'NR==2 {print "根磁碟可用:"$4, "已用:"$5}'
3. 回滾:tarball + plist 二合一恢復流程
回滾失敗最常見的原因不是二進位版本沒降回去,而是設定鍵與舊版本不相容。新版本升級時可能新增了必填欄位,回滾二進位後舊設定反而觸發 Gateway 啟動報錯。正確的回滾順序是:先 bootout 服務 → 還原 tarball 設定 → 降級二進位 → 重新 bootstrap。
# 步驟 1:停止目前服務 launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.gateway.plist # 步驟 2:還原設定 tarball tar xzf openclaw-config-20260604.tar.gz -C / # 步驟 3:降級 npm 套件到凍結版本 npm install -g openclaw@1.x.x # 替換為記錄的舊版本號 # 步驟 4:重新啟動服務 launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.openclaw.gateway.plist # 步驟 5:驗證(等待約 10 秒) sleep 10 && curl -fsS http://127.0.0.1:18789/health && echo "回滾成功"
如果 plist 路徑在升級過程中發生變化,bootout 時需要指向新 plist 路徑,bootstrap 時使用還原後的舊 plist。兩步的路徑不一定相同,這是回滾時最容易踩的坑。建議在升級前用 diff 比對新舊 plist,把差異記錄在 upgrade-memo 裡。
4. Tailscale 與 SSH/rsync:什麼場景用哪個
「我們該用 Tailscale 還是直連 SSH」這個討論沒有標準答案——兩者不互斥,適合的場景不同。Tailscale 的核心價值是多終端、跨區的隨身存取,無需設定防火牆規則;SSH/rsync 的核心價值是大檔案批量傳輸,速度瓶頸在出口頻寬而不是協定開銷。
| 維度 | Tailscale WireGuard 隧道 | SSH / rsync 直連 + 加密傳輸 |
|---|---|---|
| 推薦場景 | 隨身裝置開啟 Dashboard、團隊多人遠端存取、跨區 VPN 控制面 | CI 製品下載、日誌包批量拉取、TB 級大檔案定期同步 |
| 延遲特性 | DERP 中繼時延遲略高(~50ms 亞太←→加拿大),直連時接近裸 RTT | 裸 TCP,延遲低;但需要埠開放或跳板 |
| 頻寬消耗 | 協定開銷約 +5%,適合持續低流量會話 | 建議 --bwlimit 限速,防止打滿加拿大出口 |
| 權限管理 | Tailscale ACL 按裝置/使用者精細控制 | SSH key 管理,authorized_keys 需定期稽核 |
| 排障入口 | ACL 規則、DERP 節點、MagicDNS 解析 | 路由可達性、MTU、連線逾時與斷點續傳 |
# 從加拿大節點拉取日誌包,限速 50 MB/s,斷點續傳 rsync -avz --bwlimit=50000 --partial \ user@canada-m4.hashvps.com:~/.openclaw/logs/archive/ \ ./local-logs/ # 驗證 Tailscale 直連狀態(非 DERP 中繼) tailscale ping canada-m4 --until-direct
5. 日誌磁碟規劃:logrotate 設定與分割區建議
Gateway 異常退出有相當一部分原因是根磁碟寫滿。OpenClaw 預設把日誌寫在使用者目錄下,而 npm 全域快取也在同一個卷上;兩者疊加,加上 Xcode 匯出或 CI 製品暫存檔,幾週內就可以把一塊 512GB 的磁碟填滿。分割區或獨立 logrotate 是解決方案,而不是「定期手動 rm」。
/Users/mac/.openclaw/logs/*.log {
daily
rotate 7
compress
missingok
notifempty
dateext
copytruncate
}
# 加入 crontab(每天凌晨 3 點執行)
# crontab -e 裡新增:
# 0 3 * * * /usr/local/bin/logrotate /Users/mac/.openclaw/logrotate.conf
對於 npm 快取,可用 npm config set cache-max 10240 限制快取不超過 10GB,同時在升級完成後執行 npm cache clean --force 清理升級遺留的舊套件快取。如果機器配置是 1TB 磁碟,推薦把 ~/.openclaw/logs 和 npm 快取移至獨立的卷或磁碟分割區,與根磁碟完全隔離;即使日誌意外暴增,也不會影響 Gateway 程序的運行。
6. FAQ:六個高頻維運問題
Gateway 18789 健康檢查回傳非 200,第一步查哪裡?
先跑 lsof -nP -iTCP:18789 -sTCP:LISTEN 確認埠是否在監聽。如果沒有輸出,說明程序沒起來,用 launchctl list | grep openclaw 看 launchd 狀態,再查 ~/.openclaw/logs/gateway.log 最後 50 行的錯誤原因。如果埠在監聽但 HTTP 回傳 500,通常是設定鍵錯誤,對比升級前的 config tarball。
回滾後 plist 路徑需要手動修改嗎?
取決於升級時 plist 是否有改動。如果只是 npm 套件版本升級而安裝腳本沒有重寫 plist,還原 tarball 後路徑不變。如果新版本的安裝腳本修改了 ProgramArguments,還原後需要手動把 plist 裡的路徑改回舊版二進位的位置,再執行 bootstrap。這就是為什麼升級前要 diff 新舊 plist。
多台節點同時升級還是逐台?
強烈建議逐台。先升黃金樣機,觀察 24 小時內的 Gateway 健康和 Channel SLA;無異常後再逐台滾動生產節點,每台間隔至少 30 分鐘。全量同時升級的風險是:如果新版本存在設定不相容,所有節點同時失敗,沒有對照組。
Dashboard 顯示 CPU 100%,是 OpenClaw 本身的問題嗎?
不一定。先用 top -o cpu 或 Activity Monitor 定位實際耗 CPU 的 pid。OpenClaw 的 Gateway 程序在正常狀態下 CPU 佔用應在 1-5% 以內;如果是 node 程序佔高,檢查是否有大量 Channel 請求積壓或日誌寫入異常。另一個常見原因是 Xcode 建置程序與 OpenClaw 程序共用資源,可以透過 renice 調整優先順序。
Tailscale 連上了,但 Dashboard 仍然無法存取?
檢查 Tailscale ACL 是否允許該裝置存取 18789 埠。其次確認 MagicDNS 是否解析正確,用 tailscale ip -4 拿到 tailnet IP 後直接 curl 該 IP:18789 測試。如果直接 IP 能通而 MagicDNS 不行,是 DNS 解析問題而不是 Gateway 問題。
logrotate 執行後日誌檔案消失,Gateway 還在寫入嗎?
使用了 copytruncate 選項時,logrotate 先複製檔案再清零原始檔案,程序的檔案描述符不變,不會出現「找不到日誌控制代碼」的問題。如果用的是預設 create 模式,需要給 Gateway 發送 SIGHUP 訊號讓它重新開啟日誌檔案,或者在 logrotate 設定裡加 postrotate 腳本執行 launchctl kickstart。推薦用 copytruncate 避免服務中斷。
在專屬雲端 Mac mini 上,這份 Runbook 才真正跑得穩
一份好的維運 Runbook 有個隱含前提:機器本身行為可預期。共用資源的環境裡,同一份 curl 18789 探針今天 200、明天逾時,不是 Gateway 設定問題,是底層資源被鄰居擠占。Hashvps 提供的加拿大 M4 Mac mini 是專屬裸機節點:沒有超賣的 CPU 和記憶體,4W 待機功耗下 7×24 在線,launchd 行為與本機 Mac 完全一致,升級與回滾的 30 分鐘窗口是真實可兌現的。macOS 的 Gatekeeper + SIP + FileVault 三重機制讓 Gateway token 和 Channel 設定存放更安全,無需在安全群組規則上額外花時間。
如果你希望把本文這套 Runbook 落地到一個行為穩定、可稽核的節點上, Hashvps 雲端 Mac mini M4 是目前最直接的起點—— 立即了解套餐方案 ,把 OpenClaw 維運從「跑通了就行」升級到「有 SLA 的生產節點」。