Xcode 建置日誌突然出現 No space left on device,但工作區、快取或歸檔究竟是哪一類資料塞滿磁碟,通常無法只靠錯誤行判斷。

最快且風險最低的做法,是先停止繼續寫盤,保留第一個有效錯誤與磁碟現況,再按工作區、DerivedData、Simulator runtime、歸檔和套件管理快取逐項定位;只刪除已停止任務產生、確認沒有被使用且可以重新產生的資料。清理後若正常工作負載仍持續耗盡空間,應調整保留策略、隔離任務或擴容,不要反覆執行全盤刪除。

本文適合正在搶修 Xcode 建置的值班開發者、維護共享遠端 Mac Runner 的 DevOps 工程師,以及需要判斷清理、重建或擴容的節點平台負責人。

01

先用時間表凍結現場,再決定清理範圍

0–10 分鐘:停止新增寫入

先暫停重試中的流水線、排程建置與並行測試,避免多個工作同時繼續產生中間檔案。不要一開始刪除整個專案目錄、重建節點,或直接執行來源不明的批量清理腳本;這些動作可能破壞尚未交付的 xcarchive、簽署相關診斷資料或故障證據。

在實際執行帳戶下保留錯誤上下文,並記錄當時的提交、Xcode 版本、建置參數、工作流識別碼與仍在執行的處理程序。Apple 的 Mac 儲存空間管理說明 可作為系統層檢查的參考,但 CI 節點的實際目錄仍必須以活動 Xcode、帳戶和流水線參數為準。

df -h /
df -i /
ps aux | grep -E '[x]codebuild|[s]imctl|[f]astlane'
du -sh "$HOME"/* 2>/dev/null | sort -h | tail

輸出不只要看可用容量,也要看 inode 是否耗盡;若 df -h 尚有空間而 df -i 顯示資源接近用盡,單純找最大檔案未必能解決寫盤失敗。du 則應在不影響執行中的任務前提下使用,並把輸出連同失敗日誌保存到故障工單。

10–20 分鐘:確認失敗邊界

要確認的證據 它回答的問題 未確認前不要做的事
工作區、臨時輸出與重複 checkout 是否只有單一任務產物異常膨脹 不要刪除整個工作區
DerivedData 與套件快取的擁有者、時間 是否由已停止任務留下可再生內容 不要清空所有快取
Simulator runtime、裝置實例與測試資料 是元件本身過多,還是測試資料累積 不要直接修改受保護目錄
xcarchive、導出包與符號檔 發布鏈路是否仍有交付資產 不要把歸檔套用一般快取規則
仍在執行的 xcodebuild 或測試工作 被檢查的目錄是否仍有人使用 不要對使用中的目錄執行 rm

Xcode 建置提示磁碟空間不足時,該先刪什麼?
先不刪任何東西,先找出本次失敗任務可追溯的暫存輸出與重複工作區;確認任務已停止、沒有發布用途,且內容可以由同一提交重新產生後,才處理這一小塊範圍。歸檔、簽署材料和仍在上傳的產物不屬於第一批清理對象。

02

值班開發者:先讓同一提交恢復一次

值班開發者的目標不是把節點「清到最乾淨」,而是以最小刪除範圍恢復單次建置,並留下可以交接的證據。

先列出工作區與暫存目錄的大小,路徑以流水線實際設定為準,不要照抄其他專案的固定位置:

WORKSPACE="/path/to/workspace"
find "$WORKSPACE" -maxdepth 2 -type f -size +500M -print 2>/dev/null
du -sh "$WORKSPACE"/* 2>/dev/null | sort -h

上例的 500M 只是檢索條件,不代表某個通用清理門檻;實際門檻應由團隊的保留政策決定。可處理的通常是已停止工作留下的臨時輸出、重複 checkout 或已確認可重建的打包中間檔。源碼、鎖定檔、環境設定、尚未交付的歸檔,以及正在被其他任務使用的目錄,都應保留。

清理後必須使用相同提交與相同建置參數重跑一次,並比較編譯、測試與產物生成是否都恢復。若空間在建置開始後又快速下降,應立刻停止重試,把 dfdu、處理程序清單和失敗日誌交給建置維護者;反覆重跑只會製造更多難以區分的產物。

03

建置維護者:把 DerivedData 與快取分開治理

DerivedData、Swift Package 快取、Homebrew 或其他工具快取的用途不同,不能因為名稱含有 cache 就全部視為垃圾。Apple 的 Xcode 命令列工具說明 可協助核對目前使用的命令列流程,但實際位置仍應從活動 Xcode 與流水線環境取得。

資料類別 清理前要核對 通常可保留的理由 交接條件
DerivedData 專案、帳戶、最後使用時間、是否有並行建置 可避免下一次完整索引與重新編譯 完成乾淨建置與第二次重用建置
Swift Package 快取 依賴版本、目前是否正在解析 可減少重新解析和下載 依賴解析、編譯與測試均成功
Homebrew 或工具快取 工具版本、其他工作流是否共用 可能是多個任務的共同輸入 相關工具可正常啟動
任務暫存輸出 任務狀態、是否有交付用途 已停止且可重產時釋放風險較低 同一提交重新產出成功

DerivedData 可以在遠端 Mac CI 上直接刪除嗎?
只有在所有使用該目錄的建置已停止,並且已確認內容不是唯一交付證據時,才可刪除指定專案或指定帳戶的 DerivedData。直接刪除可能讓下一次工作流重新索引、重新編譯或重新解析依賴,因此「命令返回成功」不等於 CI 已恢復。

比起寬泛地清空家目錄,建置維護者應先鎖定活動任務,再採用明確的專案路徑:

DERIVED_DATA="/path/to/derived-data"
du -sh "$DERIVED_DATA" 2>/dev/null
# 確認沒有並行任務後,再由維護流程刪除指定專案內容
find "$DERIVED_DATA" -mindepth 1 -maxdepth 1 -type d -print

清理驗收至少包括一次乾淨建置和一次能重用既有產物的建置;若第二次仍然把空間推向滿載,問題可能在保留策略、並行度或節點容量,而不是單一快取。

04

測試負責人:分辨 Simulator runtime 與裝置資料

iOS Simulator 的空間問題常被誤判成「刪掉所有模擬器即可」。實際上,已安裝的 runtime、模擬裝置實例、測試生成資料和應用程式容器是不同責任範圍;測試矩陣仍需要的 runtime 不應因為短期缺空間而移除。

先用受支援的工具列出現有項目,再決定處理對象。Apple 的 Xcode 元件管理文件模擬裝置管理文件在模擬或實體裝置執行 App 的說明 應優先於社群批量刪除指令。

xcrun simctl list runtimes
xcrun simctl list devices
xcrun simctl help

iOS Simulator 佔用空間過大時,怎樣清理才安全?
先確認目前測試矩陣需要哪些 runtime、哪些裝置仍被工作流引用,再透過 Xcode 官方元件管理入口或本機 simctl help 顯示的受支援操作處理不用的項目。不要直接改寫系統保護目錄,也不要在測試仍執行時刪除裝置資料。

清理後要重新驗收四件事:目標 runtime 能否被辨識、測試裝置能否啟動、測試能否完成,以及 Runner 斷線後重新連線是否仍可恢復。若測試負責人無法說明某個 runtime 的擁有者或保留理由,應先把它標記為待確認,而不是直接移除。

05

發布負責人:歸檔和簽署資產不可當作快取

xcarchive、導出包、符號檔與上傳中間產物具有發布或診斷價值。Apple 的應用程式歸檔與發布流程以及除錯資訊與歸檔說明可用來核對歸檔和除錯資訊在交付流程中的角色。

發布負責人應先把每個產物標記為「尚未導出」「已導出待驗證」「已上傳待確認」或「已按政策保存」。只有已完成交付、符合留存政策、且存在可核對副本的產物,才可進入遷移或刪除流程。正在上傳的包、唯一的歸檔、符號檔,以及用於簽署的鑰匙串、憑證和描述檔,不能被當成釋放空間的對象。

歸檔處理後應重新完成導出、驗證或上傳鏈路;若只看到建置命令成功,卻沒有確認發布產物可用,不能宣稱節點已修復。

06

平台負責人:用責任清單判斷清理、重建或擴容

當一次故障結束後,平台負責人要把「誰擁有資料、何時能刪、刪除後怎樣驗收」寫進 Runner 管理流程。共享 Mac Runner 不應依賴人工定期整盤清空,因為這會同時破壞快取命中率、診斷證據和發布資產。

遠端 Mac CI 的容量治理勾選清單

  • [ ] 每個工作流都有明確的工作區、DerivedData、Simulator 與歸檔擁有者。
  • [ ] 任務結束後,只清理已停止且可重新產生的暫存輸出。
  • [ ] 發布完成後,依留存政策處理 xcarchive、導出包與符號檔。
  • [ ] 節點重啟前,確認沒有仍在執行的 xcodebuild、測試或上傳工作。
  • [ ] 清理後以相同提交重新建置,而不是只檢查清理命令的返回值。
  • [ ] 乾淨建置和第二次重用建置都完成,Simulator 測試也能啟動。
  • [ ] 歸檔、導出或上傳鏈路通過,簽署材料未被誤刪。
  • [ ] 保留策略按專案、帳戶和任務類型區分,而不是對整台節點套用單一規則。
  • [ ] 正常保留範圍若已超過節點可用容量,已提出隔離節點、縮短閒置留存或擴容方案。

共享 Mac Runner 怎樣避免磁碟再次寫滿?
先把工作區、快取、Simulator 和發布資產分成不同保留責任,再在任務結束、發布完成與節點重啟前設定可觀察的清理驗收。若多個專案共用同一節點,還要記錄帳戶、任務類型和並行工作對空間的影響,否則一次成功的清理仍可能很快被下一批任務抵消。

Xcode 歸檔失敗後,應清理節點還是擴容?
若失敗原因是已停止任務留下的可再生資料,先按上述順序做小範圍清理;若保留必要的工作區、Simulator、快取和發布資產後仍長期沒有餘裕,便不應繼續全盤刪除。此時可把建置與發布任務拆到不同節點、縮短閒置產物的保存時間,或選擇更合適的遠端 Mac 儲存設定。

需要長期維護節點時,可先參考遠端 Mac 建置節點的方案資訊,再用真實專案驗收可用儲存空間、Simulator 測試、歸檔和重啟恢復,而不是只比較標稱規格。若團隊同時需要跨地區連線,也可將香港遠端 Mac 方案作為測試節點選擇之一,但仍應以實際工作流驗收結果作決定。

07

清理完成後的恢復判定

Xcode No space left on device 的修復完成條件,不是 df 顯示出可用空間,而是整條交付鏈路再次成立:

  1. 以同一提交和建置參數完成建置。
  2. DerivedData 或依賴快取清理後,第二次建置仍能正常運作。
  3. 目標 iOS Simulator runtime 可辨識,裝置能啟動並完成測試。
  4. xcarchive 能產生,導出或上傳流程沒有因簽署資料缺失而中斷。
  5. 節點重啟或 Runner 重新連線後,任務仍能依保留政策運作。
  6. 平台負責人能說明下一次清理的觸發條件、資料擁有者與恢復入口。

若目前使用的是 Windows 或 Linux 主機加上臨時虛擬化方案,常見缺點是無法直接提供完整的 Apple 工具鏈、Simulator 行為與簽署交付流程;本地低規格 Mac 則可能把建置、測試和發布長期擠在同一個儲存空間中,導致容量治理與任務隔離都變得困難。對於需要臨時驗證、持續執行遠端 Mac CI,或想先用真實專案比較節點恢復能力的團隊,租用 NodeMini 的遠端 Mac,通常比反覆重建不透明的工作環境更容易驗收;但若工作負載長期高強度、必須接實體裝置或需要本地互動除錯,自購 Mac 或保留本地 Mac 仍可能更合適。