雲端 Mac 的 Xcode 磁碟容量監控與安全清理

CI/CD 實踐 ·約 7 分鐘閱讀

雲端 Mac 的 Xcode 磁碟容量監控與安全清理

一台長期用於封存與自動化測試的雲端 Mac,最常見的故障未必出在程式碼。Xcode 會持續寫入 DerivedData、封存檔、裝置支援檔案與模擬器資料;當磁碟接近滿載時,編譯器可能回報看似無關的寫入錯誤,簽署流程也可能只留下不完整的產物。可靠的處理方式並不是定期清空所有目錄,而是先量化空間用量、建立建置門檻,再依資料的可恢復程度逐層清理。

先建立磁碟用量基準

先記錄系統的可用空間,再檢查開發相關目錄。df 用來確認檔案系統還能寫入多少資料,du 則用來找出空間由哪些目錄占用。兩者無法互相取代。

df -Pk /

for path in \
  "$HOME/Library/Developer/Xcode/DerivedData" \
  "$HOME/Library/Developer/Xcode/Archives" \
  "$HOME/Library/Developer/CoreSimulator" \
  "$HOME/Library/Developer/Xcode/iOS DeviceSupport"
do
  if [ -e "$path" ]; then
    du -sk "$path"
  fi
done

建議分別在一次乾淨建置開始前、封存完成後,以及測試結束後取樣。這三組數據可以反映單次工作的空間增量,也能避免把正常的用量高峰誤判為空間洩漏。若要進一步找出 DerivedData 內占用較大的目錄,可執行:

du -sk "$HOME/Library/Developer/Xcode/DerivedData"/* 2>/dev/null \
  | sort -nr \
  | head -20

APFS 顯示的可用空間可能會受到可清除資料影響。建置門檻應以 df 回報的可用區塊為準,不要只根據目錄的標示大小判斷工作一定能夠完成。

為建置設定明確的容量門檻

容量門檻應根據實際尖峰用量決定,而不是憑經驗寫死。可以先以 30GB 為起點,記錄完整封存流程中的最低剩餘空間;穩定執行數次後,再將門檻調整為尖峰增量的 1.5 倍,並額外納入匯出產物所需的空間。

下列指令稿可放在管線最前端。空間不足時會以狀態碼 75 結束,讓排程器將工作標記為暫時無法執行,而不是啟動一個極可能失敗的建置。

#!/bin/zsh
set -euo pipefail

minimum_kb=$((30 * 1024 * 1024))
available_kb=$(df -Pk / | awk 'NR == 2 {print $4}')

if (( available_kb < minimum_kb )); then
  printf 'Insufficient disk capacity: %s KB available
' "$available_kb"
  exit 75
fi

printf 'Disk capacity check passed: %s KB available
' "$available_kb"

門檻值應針對每個節點分別保存。不同的 Xcode 版本、模擬器組合與專案規模會產生不同的尖峰用量,不應以小型專案的結果替大型工作區提供容量保證。

將每次建置限制在獨立目錄中

共用預設 DerivedData 的問題不只在於容量,還包括難以判斷每個目錄究竟屬於哪一項工作。為工作區指定獨立路徑後,工作結束時即可精準刪除相關資料,而不會影響其他仍在執行的建置。

job_root="$HOME/build-jobs/$BUILD_ID"
derived_data="$job_root/DerivedData"
archive_path="$job_root/artifacts/App.xcarchive"

mkdir -p "$job_root/artifacts"

xcodebuild \
  -workspace App.xcworkspace \
  -scheme App \
  -configuration Release \
  -derivedDataPath "$derived_data" \
  -archivePath "$archive_path" \
  archive

BUILD_ID 應由工作系統提供,且只能包含英文字母、數字、句點、底線或連字號。清理前還必須驗證目標路徑位於 build-jobs 之下,避免空變數讓刪除範圍意外擴大至家目錄。

依可恢復程度分層清理

清理順序應從能夠重新產生的資料開始,最後才處理需要人工確認的封存檔。

層級 資料 建議動作 主要邊界
1 已結束工作的 DerivedData 依工作目錄刪除 確認沒有建置程序仍在使用
2 已無法使用的模擬器記錄 使用 simctl 清理 不直接刪除 Devices 目錄
3 舊版裝置支援檔案 依實際測試版本複核 保留仍需除錯的系統版本
4 xcarchive 與 dSYM 人工核對後移出 已發布版本必須可追溯

移除失效的模擬器應交由系統工具處理:

xcrun simctl delete unavailable

不要直接清空 CoreSimulator/Devices。當檔案目錄與模擬器服務的狀態不一致時,後續建立與啟動裝置將出現更難排查的問題。封存目錄也不適合僅以「超過若干天」為條件直接刪除,因為 xcarchive 中可能保存已發布版本對應的 dSYM。正確做法是先登記版本、建置編號與移出位置,再刪除本機副本。

自動化清理時避開三個陷阱

第一,不要在建置期間清理共用目錄。即使某個檔案看起來已經很舊,編譯器仍可能透過索引或中間產物參照它。清理工作應取得節點層級的鎖定,或僅操作已標記為完成的獨立工作目錄。

第二,不要把「清理成功」等同於「空間已經釋放」。刪除後應再次執行 df -Pk /,確認可用區塊確實增加;如果沒有變化,應繼續檢查仍被程序開啟的檔案,而不是反覆執行刪除命令。

第三,不要讓指令稿自行判斷封存檔是否重要。無人值守的工作只應負責列出候選項目,例如產生目錄大小、最後修改時間與關聯的建置編號;是否移出或刪除,應依發布記錄決定。

以一次可重複建置完成驗收

清理完成後,至少執行一次與正式工作相同的封存流程。驗收時應記錄開始容量、最低容量、結束容量、封存路徑與結束狀態,並檢查 .xcarchive 是否完整產生。若節點也負責模擬器測試,還應將測試矩陣中每個保留版本各啟動一次,確認裝置可以正常建立、啟動與關閉。

最終檢查項目可以保持精簡:建置前門檻已通過;工作使用獨立的 DerivedData;結束後沒有殘留的編譯程序;封存檔與 dSYM 已登記;simctl list 中沒有異常裝置;磁碟剩餘空間高於下一次工作的門檻。只有同時符合這些條件,清理流程才算真正閉環。

常見問題

Xcode 建置節點至少要保留多少磁碟空間?

沒有適合所有專案的固定值。可先以 30GB 作為建置前最低門檻,再依完整封存的峰值調整;大型多模組專案至少應保留最近峰值的 1.5 倍。

可以直接刪除整個 DerivedData 目錄嗎?

可以,但必須先確認沒有建置程序正在使用。較穩妥的方法是為每個工作區指定獨立 DerivedDataPath,只刪除已完成工作的目錄。

哪些 Xcode 檔案不應自動刪除?

未完成的封存、尚未備份的 xcarchive、發布版本對應的 dSYM,以及測試矩陣仍在使用的模擬器裝置,都不應交給無人值守清理。

獨享實體節點

讓可重現的環境固定在同一台雲端 Mac 上

選擇固定的機型、地區與租用期間,透過完整的 macOS 圖形介面與命令列完成開發或自動化工作。

立即租用雲端 Mac