症狀: Mac 已經可以 SSH,GitLab 頁面上的 Runner 卻仍顯示離線。
最快解法: 先確認圖形登入會話,再查使用者級 LaunchAgent;不要一開始就重裝 Runner,也不要擅自改成 LaunchDaemon。

GitLab 官方確認,macOS 上的 GitLab Runner 常駐服務採用使用者級 LaunchAgent。這個服務依賴已登入使用者的圖形工作階段;涉及程式碼簽署、Keychain 或 iOS Simulator 時,恢復正確的登入會話尤其重要。GitLab macOS 安裝與服務模式文件 已說明相關限制。

這篇適合以下讀者:

  • 維護單台遠端 Mac CI 節點,重啟後經常要手動恢復 Runner 的獨立開發者。
  • 管理多專案 GitLab Runner、簽名與模擬器工作的 DevOps 或發布工程師。
  • 需要制定遠端 Mac 節點交付、重啟和故障驗收標準的平台團隊。

先把「離線」拆成四種狀態

一個常見失敗案例是:你先用 SSH 登入 Mac,確認 Shell 可以執行;但回到 GitLab 頁面,Runner 仍顯示 offline。此時「主機已恢復」只證明網路路徑和 SSH 服務正常,不能證明 Runner 進程、平台連線或工作匹配都正常。

請依照由外到內的順序取證:

  • 主機層: DNS、IP、SSH、磁碟空間與系統時間是否正常。
  • 使用者會話層: 目標 macOS 使用者是否真正登入圖形介面,而不是只建立 SSH 工作階段。
  • 服務層: LaunchAgent 是否載入,Runner 二進位檔與 plist 路徑是否仍可讀取。
  • Runner 層: 進程是否運作、是否能連回 GitLab、註冊資訊是否有效。
  • 工作層: Runner 是否具備工作要求的 tags,Shell executor 是否仍有權限執行建置。

每一層都有停止條件。若 SSH 不通,先不要查 Runner;若進程不存在,先不要調整 CI 標籤;若 Runner 已在線但工作排隊,則不要重裝服務。

可先執行以下取證命令,將 <RUNNER_USER><RUNNER_CONFIG><PROJECT_PATH> 替換為實際值:

whoami
scutil --get ComputerName
ps aux | grep '[g]itlab-runner'
gitlab-runner status
gitlab-runner verify

gitlab-runner statusverify 以及設定檔相關命令的用途,應以 GitLab Runner 官方命令文件 為準。不要把終端機沒有輸出,直接解讀為服務正常;你還需要把進程、日誌與 GitLab 介面時間線對起來。

先恢復圖形登入,再判斷 LaunchAgent

macOS 的 LaunchAgent 代表已登入使用者執行。GitLab 官方並不把系統級 LaunchDaemon 當作 macOS Runner 的替代服務模式。Apple 的 Service Management 說明 也將這類背景項目與使用者工作階段分開處理。

因此,重啟後先在遠端 Mac 上確認:

id
echo "$HOME"
launchctl print "gui/$(id -u)" 2>/dev/null

如果 HOME 不是預期的 Runner 使用者目錄,或 launchctl print 找不到對應 GUI domain,你目前很可能只進入了 SSH 工作階段。這時不要在 SSH 中強行建立服務,也不要把 plist 複製到 /Library/LaunchDaemons 來繞過問題。

請改用以下方式處理:

  • 透過 VNC 或網頁控制台進入 Mac 的圖形登入畫面。
  • 使用與 Runner 註冊相同的使用者登入 macOS。
  • 在該圖形會話的終端機執行 GitLab 官方安裝或服務命令。
  • 再回到 SSH,檢查進程、服務狀態和 GitLab 頁面時間線。
  • 若仍失敗,保留現有設定後再查 plist 和日誌,不要立即刪除註冊資料。

普通命令列建置有時只需要 Shell 和檔案權限;但程式碼簽署、Keychain 存取和 Simulator 通常需要正確的使用者會話。這是「Runner 在線」與「Xcode 工作真的可執行」之間最容易被忽略的差異。

FileVault 與自動登入不是同一個修復按鈕

啟用 FileVault 後,Mac 重新啟動可能停在磁碟解鎖流程,直到有人在主機端或圖形控制台輸入解鎖資訊。Apple 的自動登入支援文件 說明,自動登入可能受到 FileVault 或組織管理政策限制。

你應把安全性和可用性分開決策:

  • 組織要求保留 FileVault,就安排受控的遠端圖形解鎖流程。
  • 沒有圖形控制台時,不要假定 SSH 能讓 LaunchAgent 自動恢復。
  • 需要簽名金鑰的正式節點,先確認 Keychain 解鎖策略,再談自動登入。
  • 若只能靠人工登入才能恢復,應把它記錄為交付限制,而不是宣稱節點具備無人值守能力。

注意: 為了讓 Runner 重啟後自動上線而關閉 FileVault,會改變磁碟加密和實體失竊風險。除非安全政策、裝置管理和事故責任都已確認,否則不要把它當成預設修復方案。

依序檢查 plist、路徑與權限

當圖形會話已恢復,下一步才是確認服務檔案。你要查的是「服務是否能被該使用者載入」,不是單純尋找任何名為 Runner 的進程。

先檢查實際檔案:

ls -l "$HOME/Library/LaunchAgents"
find "$HOME/Library/LaunchAgents" -maxdepth 1 -type f -iname '*runner*' -print
command -v gitlab-runner
gitlab-runner list

接著核對以下項目:

  • plist 的擁有者是否為預期使用者。
  • plist 內的 ProgramArguments 是否指向仍存在的 Runner 二進位檔。
  • --config 指向的設定檔是否存在,且沒有被另一個帳戶擁有。
  • StandardOutPathStandardErrorPath 的父目錄是否存在並可寫入。
  • 日誌目錄是否位於可持久化磁碟,而不是重啟後會清空的暫存位置。
  • 服務使用的環境變數是否包含 Homebrew、Ruby、Node 或 Xcode 工具鏈需要的路徑。

GitLab 的進階設定文件 可用來核對設定檔和執行參數。請把敏感令牌、專案名稱、主機名稱與憑證內容替換成 <TOKEN><PROJECT><HOST><CERTIFICATE> 後,再保存診斷紀錄。

官方 macOS 排障文件列出 killed: 9exit status 134Load failed: 5 等不同失敗現象。GitLab Runner macOS 故障排查說明 對應的處理方向並不相同:

  • killed: 9:先查二進位檔是否能執行、路徑是否正確,以及系統是否終止了進程。
  • exit status 134:保留完整 stderr 和系統日誌,確認是程式崩潰、環境問題還是設定錯誤。
  • Load failed: 5:先查 plist 格式、檔案權限、GUI domain 和服務載入上下文。

只有在服務檔案確實損壞,或二進位檔與現有設定無法恢復時,才考慮重裝。重裝前先複製原設定檔、註冊資訊、日誌和自訂環境變數,否則你可能把「服務未啟動」變成「服務和 Runner 身分都遺失」。

用對比表判斷故障邊界

你看到的現象 優先檢查 不要先做的事 通過條件
SSH 無法連線 主機、電源、網路與遠端存取通道 重裝 Runner SSH 可穩定登入
SSH 正常,Runner 離線 圖形登入、LaunchAgent、plist 與進程 改成 LaunchDaemon 進程存在且平台狀態更新
Runner 在線,工作排隊 tags、專案允許範圍與 Runner 忙碌狀態 重啟整台 Mac 工作能被該 Runner 接收
Shell 工作成功,簽名失敗 使用者會話、Keychain、憑證與 Xcode 環境 只增加 CPU 或重註冊 簽名任務在重啟後仍成功
普通工作成功,Simulator 失敗 GUI 會話、Simulator 狀態與顯示環境 宣稱節點已完全恢復 測試任務完成且結果可追溯

這張表的重點是分開「服務常駐」和「任務可執行」。遠端 Mac 可以讓 Runner 顯示在線,卻因 tags 不匹配而完全不領取工作。GitLab 官方的Runner 標籤匹配規則 指出,工作指定的 tags 必須與可用 Runner 的標籤符合;否則工作會留在排隊狀態。

把連線、註冊與 Shell 權限分開處理

當進程存在,請觀察 Runner 日誌,而不是只看頁面上的綠色狀態:

gitlab-runner verify --config <RUNNER_CONFIG>
tail -n 100 <RUNNER_LOG>

若出現連線逾時,檢查 DNS、出口頻寬、代理設定、企業防火牆和憑證鏈。若顯示註冊或授權失效,先核對目前設定檔使用的 URL、Runner 身分和令牌狀態。不要因為網路中斷就重新註冊,這可能製造多個沒有明確用途的 Runner。

接著核對工作定義:

  • .gitlab-ci.yml 的 tags 是否指向這台 macOS Runner。
  • Runner 是否被限制只能服務指定專案。
  • 工作是否卡在其他 stage、手動核准或資源鎖。
  • Runner 是否已有長時間執行中的工作。
  • Shell executor 使用的帳戶是否能存取 Xcode、憑證、專案目錄和必要命令。

Shell executor 會直接繼承 Runner 使用者的權限。GitLab 的Shell executor 安全文件 明確提醒,這類執行器只適合可信任的專案與工作。共享節點若讓不相關專案共用帳戶,可能造成原始碼、SSH 金鑰、Keychain 或建置憑證暴露。

較穩妥的做法是:

  • 生產簽名節點只接收受信任專案。
  • 將測試 Runner 與正式發布 Runner 分開。
  • 以最小權限建立工作目錄和憑證存取範圍。
  • 把 Runner 設為專案專用,並在日誌中遮罩令牌。
  • 發現不明工作進入共享節點時,先停用接收新工作,再保留現場證據。

FAQ:針對重啟後離線的四個判斷

為什麼 Mac 重新啟動後 GitLab Runner 沒有自動上線?

macOS 版 GitLab Runner 是以已登入使用者的 LaunchAgent 執行,不是系統層級的 LaunchDaemon。若重啟後停在登入畫面、服務由錯誤的 SSH 工作階段載入,或 plist、日誌目錄權限不正確,Runner 可能仍然離線。先確認圖形會話,再查看服務與進程。

用 SSH 啟動 GitLab Runner 時找不到 launchctl domain,應如何處理?

這通常表示目前 SSH 工作階段沒有對應的使用者 GUI bootstrap domain。不要在 SSH 中反覆重載或直接刪除設定;改用 VNC 或網頁控制台進入同一個 macOS 圖形登入會話,在該會話的終端機重新執行服務安裝或啟動命令,再檢查 LaunchAgent 狀態。

Runner 顯示在線,但 macOS CI 工作為什麼一直排隊?

Runner 進程在線只代表它能與 GitLab 通訊,不代表一定符合工作需求。檢查工作使用的 tags 是否與 Runner 完全匹配、Runner 是否允許接收該專案工作,以及是否被忙碌中的任務佔用。若標籤不符,平台會讓工作持續等待,即使頁面顯示 Runner 在線。

開啟 FileVault 後,如何恢復遠端 Mac Runner?

FileVault 會改變重啟後的解鎖流程,遠端主機可能停在需要本機輸入的畫面。先保留 SSH 與圖形控制台兩條管理通道,透過受控的 VNC 或網頁控制台完成解鎖與使用者登入,再確認 LaunchAgent、Keychain 和 Simulator 任務。不要為了自動登入而擅自關閉 FileVault,應先遵循組織安全政策。

用可勾選清單完成一次真實重啟驗收

不要以一次「頁面重新變綠」作為修復完成標準。至少要在隔離節點執行以下驗收,並保存時間、命令輸出和工作結果:

  • [ ] 讓一個普通 Shell 建置正常完成,確認 Runner 能接收工作。
  • [ ] 正常結束工作後重新啟動 Mac,記錄重啟前的 Runner 狀態。
  • [ ] 透過圖形控制台完成必要的磁碟解鎖和使用者登入。
  • [ ] 從 SSH 檢查主機可達性、使用者身分與 GUI domain。
  • [ ] 確認 LaunchAgent 已載入,Runner 進程與日誌均有新活動。
  • [ ] 在 GitLab 頁面確認 Runner 的連線時間已更新。
  • [ ] 執行指定 tags 的 macOS CI 工作,排除標籤錯配。
  • [ ] 分別測試普通建置、程式碼簽署、Keychain 存取與 Simulator 工作。
  • [ ] 檢查重啟後 Xcode、憑證、模擬器和工作目錄是否仍可用。
  • [ ] 若必須人工登入或人工解鎖,將它列為節點交付限制。
  • [ ] 將錯誤日誌、設定檔版本和驗收結果保存到可追溯的變更紀錄。

如果你正在建立新節點,先閱讀macOS GitLab Runner 部署與上線驗收方向,再把本文的重啟測試加入交付流程。涉及簽名金鑰時,也應把遠端 Mac 的程式碼簽名與 Keychain 隔離 納入權限設計,而不是等到發布工作失敗才補救。

什麼情況適合改用遠端 Mac?

如果你目前把 Windows 或 Linux 主機當作主要控制端,再透過不穩定的虛擬化環境處理 macOS CI,常見缺點是:無法可靠保留使用者圖形會話、簽名與 Simulator 工作容易失敗,重啟後也缺少可視化復原通道。自建 Mac mini 伺服器則需要自行處理硬體故障、電源、網路、磁碟和遠端解鎖。

對需要短期建立 CI 節點、測試重啟恢復,或為發布週期準備備用環境的人,租用 MACCOME 的遠端 Mac 會更容易同時保留 SSH 與圖形控制台。你仍應先完成 Runner、簽名和 Simulator 的驗收;但不必為一次性的測試需求先購買並長期維護一台實體 Mac。若要比較可用的遠端 Mac 方案,可先查看遠端 Mac 算力方案,再決定是否將生產工作遷移。

真正的修復不是讓 GitLab 頁面短暫顯示在線,而是證明主機、圖形會話、LaunchAgent、Runner 連線和 CI 工作在重啟後都能恢復。完成這套驗收後,你才知道應該保留人工復原、改用具備雙通道管理的遠端 Mac,還是增加一個備用節點。