还我一个干净的Mac OS(如何彻底删除不需要的App)

当初我买MacBook Air的时候特地选择了高配版本,硬盘空间是128G(2011年的古董机器),在最开始的1-2年内使用还不错,后来发现越来越力不从心,为了尽可能腾出空间,几乎把所有的照片、视频和PDF文档都移到了云上,也经常用CleanMyMac等工具进行清理,但还是发现空间被一些已经卸载的App蚕食,既然没有更好的方案,那就自己写一个工具来清理吧。

主界面

前几节内容是比较繁琐的技术介绍,不感兴趣的同学可以直接跳到工具的使用那一节

App最喜欢的几个目录

Mac和Windows操作系统有一个很大的不同,大部分App是没有安装程序的,一般下载下来就是一个dmg文件,解开之后直接将App拖到应用程序目录下就可以了,所以给人感觉卸载也就是将App拖到废纸篓然后清空。如果真这样做就大错特错,即使一个最简单的App都会在下面几个目录中或多或少留下纪念,这些目录一般有:

  • ~/Library
  • ~/Library/Application Support
  • ~/Library/Application Support/CrashReporter
  • ~/Library/Caches
  • ~/Library/Containers
  • ~/Library/LaunchAgents
  • ~/Library/Preferences
  • ~/Library/PreferencePanes

如果一个程序是通过pkg方式安装,或者是在第一次运行时请求管理员权限,那一般还会在如下几个目录中留点纪念:

  • /Library
  • /Library/Application Support
  • /Library/Extensions
  • /Library/LaunchAgents
  • /Library/LaunchDaemons
  • /Library/PreferencePanes
  • /Library/Preferences

以上都还是只是列出了部分,不同的App由于需要还会在其他目录中安装一些文件,比如字处理软件一般会在/Library/Fonts下面安装字体,有些扩展组件会放在/Library/ScriptingAdditions下面。

限于篇幅,我不能一一介绍所有目录的内容,选几个重点的目录大概说一下:

~/Library/Application Support

这个目录可以说是App最重要的文件目录,一些App本身并不大,但是需要的支持组件和内容非常多,特别是采用第三方插件和缓存网络内容的软件,例如我用的Dash,本身的大小只有24MB左右,但是由于经常浏览资料,所以缓存了很多网络内容,使得它的Support目录达到了1.37GB!可想而知,如果只是将App扔到废纸篓,几乎不会节省任何空间。

Dash的占用空间情况

~/Library/Preferences

这个目录下保存的是App设置,一般来说,稍微有点规模的软件都有自己的配置信息,放在这里的文件虽然占空间不多,但是清理掉还是有好处的,例如有些App不能正常工作,即使卸载重装也不行,往往就是配置文件出错了,把这里清理掉之后再重装就会有比较好的效果。

~/Library/Containers

这个目录对于App Store上下载的软件来说,是最重要的一个目录,由于Apple的限制,AppStore的软件都在沙箱中运行,每个软件在沙箱都有自己的一个完整空间,对于App来说,它以为自己在一个正常的目录系统中运行,但实际上不是,操作系统重定位了读写位置到沙箱之中。
要是卸载软件的时候,只是简单的在Launchpad中点一下叉来删除,那不知道又有多少空间莫名其妙地消失了,我曾经用这种方式卸载了网易云音乐,结果后来才发现,整整417MB的空间不见了……

网易云音乐卸载之后仍然占用大量空间

~/Library/LaunchAgents

Mac上的随机启动方式之一,熟悉OS X操作系统的同学应该立刻想到了launchctl,这里就是存放启动配置文件的地方,大部分App只会往这里写启动信息,请神容易送神难,要送神,只有用第三方工具或是自己手动清理了,还有,LaunchAgents 和 LaunchDaemons 是有一些区别的,两者虽然都是随机启动,详细对比请看LaunchAgents VS LaunchDaemons

本工具的概述

直到现在我还在想,要是用Cocoa来写这个工具的话,程序会小很多,现在这个程序压缩包有40+MB,其实绝大部分都是Electron、React的框架库,真正的代码也就几个文件,加起来不到1M大小。而之所以选择用JavaScript来做,其实就是想验证一下React开发一个桌面应用到底会怎样,JavaScript是不是有一统江湖的本事?

部分代码

用JavaScript最大的顾虑也许是性能问题,程序虽然难度不大,也有几个运算比较密集的地方,一是plist信息的解析,二是正则表达式。我将plist解析放到外部库去做了,正则表达式仍然用Google的V8引擎,目前来看还行。

程序的I/O比较多,需要频繁统计文件占用空间大小,查找相关文件,读取文件信息,虽然JavaScript的最大好处是异步操作,但是在统计出结果之前,界面能做出再多的响应也没有什么意义,因此在有些地方,我没有使用异步操作,要是你感觉界面有点卡,那是我的原因,不是React的错:)

再给大家推荐一下Mac系统上自带的AppleScript,这个是Mac上的瑞士军刀,能和Windows上的Powershell有得一比,我在这个软件中最后的清理工作实质上就是通过AppleScript来完成的,例如清理工作首先要关闭目标程序,你要是自己编程打算怎样实现?枚举系统进程然后kill?用AppleScript就能非常优雅地完成,例如你打开Safari,再同时开一个终端窗口,然后在终端中输入

osascript -e 'quit app "safari"' 

名字的来由

来自于同名电影《Total Recall》,奎德在一次虚拟体验之后,突然发现自己原来不是一个默默无闻的工人,而是一个超级特工,那自己到底是什么呢?也许真正的自己永远也找不回来了,但是至少不是现在这样浑浑噩噩。

我也想借这个意思表示即使通过努力清理,也不一定能还原到最初的状态,但至少不会这么糟糕。

工具的使用

这个好像没有什么太多可以说的了,我只是对比了和CleanMyMac的清理效果,至少,在大部分情况下,我感觉还不错。

卸载百度云的对比

CleanMyMac的查找情况

可以清楚地看到,CleanMyMac没有找到百度云的Application Support目录,此外,只找到了登录项,没有找到启动项和启动文件。

Total Recall的查找情况

Total Recall不仅找到了CleanMyMac所有的内容,还找到了Application Support,这里有1.14MB空间,此外还找到了LaunchDeamons里面的启动项和启动文件,还发现了com.baidu.netdiskmac.BDYunFinderInstaller这么一个鬼……

比较一下卸载AppStore上的App

感觉找到了挺多的啊……
其实只有两个,别忽悠了

CleanMyMac列出了一大堆感觉挺吓人的,仔细看才发现其实都是Containers\com.tencent.xinWeChat这个目录里面的子目录,还拿一个系统临时目录来充数(电脑重启后系统临时目录都会清空),卸载的时候其实只要删除沙箱目录就万事大吉。

存在的不足

  • 有一类软件是以Package方式发布的,里面有复杂的安装步骤,例如Microsoft Office 2016 for Mac这样的,对于这类软件,需要分析的内容比较多,打算在完善后将Package卸载整合
  • 软件界面很简陋,一是不大会玩CSS和HTML布局,二是初次使用React,前端高手可以指点我一下

参考内容

  • 《深入解析MAC OS X & IOS操作系统》 这本书对于想了解Mac系统的人来说是不二之选,值得拥有
  • Information Property List Key Reference App里最重要的文件Info.plist的介绍,开发必备
  • Electron 如果打算用Electron构建一个桌面App,必须从这里开始
  • React React的官方网站,虽然我的界面做得挺难看,那是因为我还不怎么会玩css
  • Total Recall 百度云下载本程序

推荐阅读更多精彩内容