2026-04-16 iOS CI 磁盘清理:模拟器运行时、归档与租赁云 Mac 上的 launchd 清扫
在香港、东京、首尔、新加坡与美国东部租赁的Mac mini M4构建机上,磁盘看似永远够用,直到 df -h 显示数据卷可用空间低于约 12%——此后每一次 xcodebuild test 都像抽签。本篇以2026-04-16为时间戳,说明在已隔离编译缓存的情况下为何仍会涨盘,用表格标出最大目录,给出可复制的 simctl 维护命令,定义归档保留策略,附带 launchd 清扫模板,并串联 按作业隔离 DerivedData(2026-04-15) 与 无头模拟器测试,让卫生策略从编译到测试端到端一致。
为何「已经在清 DerivedData」磁盘仍会满
按作业设置 DERIVED_DATA_PATH 能避免编译竞态,但挡不住全局占用:为 Xcode 16.x 安装的每个 iOS 运行时仍位于 /Library/Developer/CoreSimulator;一次 UI 测试可能增加 300–900 MB 设备数据;每次归档都会复制 dSYM 与 bitcode 切片。若在同一主机轮换三个 Xcode 小版本却不卸载旧运行时,团队往往在察觉前已失去 80–140 GB。将磁盘遥测与队列深度对齐,只有在清扫边际收益递减后再通过 定价页扩容。
- 陈旧已启动模拟器 会保持 CoreSimulator 挂载,阻碍删除。
- 旧的 watchOS / tvOS 运行时 在只构建 iOS 目标时仍会长期存在。
- 归档 在共享 SSH 主机上常因无人认领保留策略而堆积。
- 部分镜像上移到
/tmp的 xcresult 包在重启后仍存在——需显式清扫。
占用地图:容量躲在哪里
| 路径 / 区域 | 常见区间 | 可否自动化? |
|---|---|---|
~/Library/Developer/Xcode/Archives |
累计约 15–120 GB | 可以,需基于日期的策略并先上传对象存储 |
~/Library/Developer/CoreSimulator/Devices |
约 8–60 GB | 部分——删除不可用设备并修剪媒体缓存 |
/Library/Developer/CoreSimulator/Volumes(运行时) |
多版本约 25–90 GB | 谨慎——与所需 SDK 矩阵对齐 |
~/Library/Developer/Xcode/iOS DeviceSupport |
约 5–25 GB | 若策略允许,可删除早于 180 天 的版本 |
/Users 与 /Volumes/builds 的 NVMe 卷可用空间低于 50 GB 时分页;低于 25 GB 时硬停止接收新作业,避免归档中途内核写失败。
运维实际在跑的 simctl 命令
仅在 CI 队列报告零个活跃模拟器作业时执行,或先将 runner 打上维护标签并排空后再操作。
xcrun simctl shutdown all
xcrun simctl delete unavailable
xcrun simctl erase all # 仅用于可丢弃的预览机——未经批准切勿在共享生产型构建机上使用
为列出运行时并决定从 Xcode「平台」面板或 xcodebuild -downloadPlatform 流程卸载哪些包,建议每周将 xcrun simctl list runtimes 输出写入配置仓库,使东京与新加坡节点保持一致。
归档:财务也能听懂的保留算术
将 .xcarchive 视为受监管制品:上传对象存储后,本地按回滚策略保留 14 或 30 天再删除。若合规要求90 天本地保留,应显式购买磁盘余量——不要指望压缩救命;对已压缩切片 zip 很少能优于 35%。
| 保留策略 | 约月度增长(单应用、每周归档) | 缓解手段 |
|---|---|---|
| 本地 7 天 | 12–20 GB | 夜间 tar + 上传 + 删除 |
| 本地 30 天 | 45–70 GB | 分层存储 + 校验和验证 |
| 无限期「以防万一」 | 无上限 | 在共享租赁 Mac 上禁止 |
使用 launchd 的清扫作业(无点运维)
将维护封装为 CI 用户拥有的非交互脚本;日志写入 ~/Library/Logs/ci-janitor.log;若任一步单次删除超过 15 GB 则非零退出以便 Slack 留痕。按区域在周日 03:00本地时间调度——香港的周日清晨在美西仍是周六晚间,跨时区团队请错峰。
~/Library/Developer/Xcode/UserData——代码片段与断点存在其中;工程师会抗议,你也会重新打开「神秘红构建」工单。
与 DerivedData 及测试策略配合
全局清扫后,仍需保证每条流水线按作业设置 DERIVED_DATA_PATH,详见 2026-04-15 隔离文章。对 UI 繁重的套件,请重读 无头模拟器测试 以限制并行 destination,避免清扫与活跃的 SimulatorTrampoline 进程冲突。
激进清扫后的观察点
首次清扫后的作业可能多花 4–11 分钟 重新下载符号或重建 DeviceSupport。请跟踪 p95 构建时间 48 小时;若涨幅超过 22%,说明策略过激进——从备份恢复或放宽保留。
常见问题:租赁 Apple Silicon 上的磁盘卫生
| 问题 | 简要回答 |
|---|---|
| 是否应把 Archives 软链到 NFS? | 仅当链路延迟足够低;否则采用上传后删除本地。 |
| Apple Silicon 会压缩 CoreSimulator 数据吗? | APFS 克隆对部分模板有帮助;不要据此做容量核算。 |
| 谁拥有清扫脚本? | 平台团队 + 轮值 on-call,文档见 帮助中心。 |
区域、NVMe 与何时再加一台 Mac
磁盘压力常常是单台主机负载过多的代理指标。若清扫每周可回收 >40 GB 而可用空间仍长期在 20% 附近徘徊,应在 JP 与 SG 构建机之间拆分团队,或增加第二台 美国东部 节点——到 Git 与 App Store Connect 的延迟与字节数同样重要。用 定价 比较裸金属档位;将 博客索引 加入书签以跟踪签名、公证与 OpenClaw 手册。
结论:在共享租赁 Mac 上,全局模拟器与归档卫生不是可选项——它决定夜间构建是可预测还是「直到有人 SSH 上去才变绿」。自动化、可度量,并与按作业的 DerivedData 纪律配套。