近日,Jenkins上的所有项目编译均失败,查Log,看到 IOException: Disk full
,便知出包机Mac的磁盘空间不足了。
这是一个非常诡异的现象,因为出包机总共有1TB的容量。我们的Jenkins策略会在构建前丢弃掉较旧的构建,以腾出磁盘空间,而且在构建前我们也会清空workspace下的artifacts目录,以保证上一次的构建不会有任何残留。
出包机本身没有装与出包无关的其他大型软件,更没有音乐,图片和视频等大文件。鉴于出包机已连续工作了近两年,执行了上千次任务,可以断定磁盘空间被出包任务慢慢占满了。那么,到底谁是凶手?
第一感是打开系统的「关于」,查看磁盘的基本占用情况,可以发现有约700GB被一个叫「容器中的其他宗卷」所占据。毫无疑问,凶手就是这个「其他宗卷」。然而它是什么?在哪里?这些都不得而知。
这时,需要换一种思路:有没有一种方式知道占据磁盘空间最多的N个文件或目录?也许其他宗卷的内容就藏身于此。第一感还是打开了系统自带的Finder,但是除了找到几个大的安装文件外一无所获,仿佛这个其他宗卷被系统隐藏了一样。
这时候,命令行思维的优势便显现了出来,很多GUI没有实现的功能都可以通过命令行获得。在一番Google后,我找到了 How to Find Biggest Files and Directories in Linux ,里面详细介绍了在*nix系统下找到大文件的命令。
在键入 du -a | sort -n -r | head -n 20
后,便出现了上图,我们可以发现 ./Libaray/Developer/Xcode/DerivedData
占据了最多的空间,而事实便是这个目录确实占据了约700GB的磁盘空间。我们找到了真凶!
DerivedData这个目录是做什么用的?
我们每次调用Xcode来构建代码时,Xcode便会在DerivedData目录下新建一个目录用来存放这次构建的中间过程文件。然而,在构建结束时,Xcode并不会删除它。所以在经历了上千次构建后,DerivedData目录就变得异常庞大。
由于DerivedData目录记录的是构建的中间过程,所以在每一次构建完成后,我们可以调用命令 rm -rf /Users/Your_User_Name/Library/Developer/Xcode/DerivedData/*
来将其删除( 注意将 Your_User_Name
替换为真实的用户名 )。
可是如果同时有多个iOS包要出的时候,我们不能简单粗暴的在每次构建完成后删除掉DerivedData,因为这样会影响其他还没有完成的构建。
我认为一个比较好的策略是定时删除,即选一个很小概率会发生构建的时间,执行一次删除命令。
具体步骤如下:
Manage Jenkins
,然后打开 Configure System
,在环境变量里填下如下图红框所示的键值对。注意把值替换为你真实的DerivedData目录路径。
执行shell
步骤,shell代码为 rm -rf ${DerivedData}/*
Build Triggers
里勾选 Build periodically
,然后写入 H 5 * * 1
,这可以保证每周一的早上五点会执行删除任务。
真凶已伏法,从此,我相信出包机再次出现磁盘空间已满问题的概率将大幅度降低。