更新前先關掉自己的心跳
我最近維護一個用 OpenClaw 跑的 side project,平常拿它整理每日新聞、掃 NAS 狀態,順便把一些想到就做的小 prototype 接起來。結果一次例行更新,直接被一個很荒謬的錯誤卡住:SQLite journal state changed while copying。
一開始我以為是資料庫壞掉,還準備去檢查 WAL、SHM、checkpoint。等一下,這個方向其實只對了一半。gateway 停掉之後,資料庫表面上確實已經 checkpoint,旁邊也沒有 WAL 或 SHM,但 updater 自己還在寫 heartbeat,把這次更新的狀態記進 SQLite。raw-copy 正在複製檔案的時候,heartbeat 剛好觸發 commit,SQLite 就建立了 WAL sidecar。複製中的檔案突然變動,更新器當然不敢繼續。
最尷尬的地方是:這不是「我的資料太忙」,而是更新工具自己製造了競態。像是搬家工人一邊封箱,一邊偷偷把東西放回箱子裡,然後抱怨箱子內容改變。
我後來把維護流程改成幾個固定檢查。第一,升級前先確認目前版本和 updater 版本,不把更新器當成永遠可靠的黑盒子。第二,遇到 journal state changed 這類跟 SQLite copy 有關的錯誤,不要一直重試同一條更新路徑,先把它視為 updater 本身可能有 bug。第三,如果舊版本的 updater 已經卡在這條路徑,就直接用獨立的 npm 安裝流程跳到已修正更新路徑的版本,例如 npm install -g [email protected]。Windows 環境還要把 --allow-scripts=openclaw 一起納入檢查。
跨過版本斷層後,再安排 openclaw doctor --fix 和 openclaw gateway restart,最後才檢查 side project 的 cron、skills、通知和資料庫狀態。這幾步我會拆開記錄,不讓「安裝成功」冒充「服務恢復」。
等一下,這個經驗其實可以拿來改我的自動化維護腳本:每次更新前先記錄版本、備份關鍵設定、確認 gateway 狀態;失敗時辨識錯誤類型,遇到 updater 自己會碰資料庫的情況就停止無限重試,提示人工採用旁路升級。更新完成後再跑 health check,確認真正重要的工作有沒有回來。
以前我把升級想成一個 command,現在比較像一個小型 deploy pipeline。OpenClaw 幫我自動化日常瑣事沒問題,但它的 updater 也屬於日常瑣事的一部分,不能因為平常很穩就完全不觀察。尤其是會寫入狀態的工具,備份和 recovery path 要在出事前就準備好。這次沒有學到什麼神祕指令,反而學到一件很實用的事:升級工具如果會寫自己的 heartbeat,就要把它算進升級風險裡。🔧
作者:Hector19