三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

VMware macOS虚拟机磁盘空间优化:从原理到实践的完整瘦身指南

VMware macOS虚拟机磁盘空间优化:从原理到实践的完整瘦身指南

1. 问题缘起:当你的macOS虚拟机变成“空间吞噬者”

如果你和我一样,长期在VMware Workstation或Fusion里跑macOS虚拟机,大概率会遇到一个让人头疼的问题:明明没装多少新软件,也没存多少大文件,但虚拟磁盘文件(通常是那个.vmdk文件)的体积却像吹气球一样,只增不减。昨天还是80GB,今天一看可能就逼近100GB了。C盘(或者你的宿主机系统盘)频频告急,红色存储空间警告弹窗成了日常。这不仅仅是浪费硬盘空间那么简单,更大的虚拟磁盘文件意味着更慢的启动速度、更滞后的快照创建时间,以及备份时成倍增长的时间和网络开销。

这个问题的本质,在于虚拟机磁盘的“单向膨胀”机制。VMware默认使用的动态分配磁盘(Thin Provisioned Disk)虽然一开始很节省空间,但它有一个特性:一旦空间被虚拟机内的系统“触及”过,这部分空间在虚拟磁盘文件中就会被标记为“已使用”,即使虚拟机里的macOS后来删除了文件,这部分空间也不会自动返还给宿主机。macOS系统本身的各种临时文件、缓存、日志、软件更新残留、Time Machine本地快照(如果开启),以及虚拟机快照的叠加,都在持续不断地“污染”这块虚拟磁盘,导致其物理占用持续增长。

网络上相关的讨论很多,但信息零散,有的方法治标不治本,有的操作甚至有风险。今天,我就结合自己多年管理和维护多个macOS虚拟机的经验,整理出一套从原理到实操的完整“瘦身”指南。我们的目标不仅仅是清理出几个GB的空间,更是要建立一套可持续的维护习惯,让你的macOS虚拟机长期保持“苗条”和高效。

2. 理解虚拟机磁盘膨胀的三大元凶

在动手清理之前,我们必须先搞清楚空间被谁“吃”了。盲目操作可能事倍功半,甚至损坏系统。根据我的观察,macOS虚拟机空间异常增长,主要来自以下三个层面。

2.1 元凶一:macOS系统自身的“垃圾”堆积

即使是一个“干净”的macOS系统,在运行过程中也会产生大量临时数据。这部分是空间占用的主要来源之一。

  • 系统与用户缓存 (~/Library/Caches,/Library/Caches): 这是重灾区。每一个App,从Safari到Xcode,都会在这里存放缓存文件。有些App的缓存清理机制并不完善,尤其是那些从第三方网站下载的软件,动辄几个GB的缓存很常见。
  • 日志文件 (~/Library/Logs,/Library/Logs,/var/log): 系统诊断和排错离不开日志,但日积月累,它们也会占据可观空间。特别是某些开发工具或后台服务的调试日志,如果不加限制,体积增长会非常快。
  • 软件更新残留: macOS每次系统更新或通过App Store更新大型软件(如Xcode、Final Cut Pro)后,都会在/Library/Updates/private/var/folders等目录留下完整的安装包或中间文件,这些文件在更新成功后通常不会被自动删除。
  • Time Machine本地快照: 如果你的macOS虚拟机开启了Time Machine(即使备份目标是网络驱动器或另一个虚拟磁盘),系统也会在本地磁盘上创建“本地快照”,用于实现“回到过去”的文件恢复功能。这些快照会占用大量空间,尤其是在频繁进行文件操作时。
  • 邮件、邮件下载附件: 邮件App默认会下载所有邮件和附件到本地,长期使用后,~/Library/Mail目录的体积可能超乎你的想象。
  • iOS设备备份: 如果你在虚拟机里连接过iPhone或iPad进行备份,~/Library/Application Support/MobileSync/Backup/目录下的备份文件也是空间杀手。

2.2 元凶二:VMware快照的“隐形”成本

VMware的快照功能是进行系统测试、软件试用的神器,但它也是导致虚拟磁盘文件膨胀的“隐形杀手”。很多人对快照的理解有误区。

快照并非仅仅保存了“差异点”的一个小文件。当你创建一个快照时,VMware会冻结当前虚拟磁盘的状态,之后所有的磁盘写入操作都会被重定向到一个新的增量磁盘文件(通常以-delta.vmdk-sesparse.vmdk为后缀)中。问题在于:

  1. 链式增长:每创建一个新快照,就会在链路上增加一个增量文件。你操作得越久,这个增量文件就越大。
  2. 删除文件不释放空间:在快照链存在的情况下,即使在虚拟机内删除了大量文件,这些“删除”操作本身也是作为新数据写入到最新的增量文件中的。原始磁盘文件中被“删除”的数据块并没有被释放,除非你删除整个快照链。
  3. 合并开销:当你删除一个早期或中间的快照时,VMware需要执行合并操作,这个过程可能会临时需要几乎两倍于该快照大小的磁盘空间。如果你的宿主机磁盘空间本就紧张,合并操作会直接失败。

一个拥有多个快照的虚拟机,其.vmdk文件的总物理占用,很可能远大于你在虚拟机内部看到的已使用空间。

2.3 元凶三:虚拟磁盘的碎片化与未回收空间

这是最底层,也最容易被忽略的原因。即使你清理了macOS内的垃圾,也管理好了快照,虚拟磁盘文件本身可能依然臃肿。

  • 文件系统碎片化:虚拟机内的macOS文件系统(APFS或HFS+)在长期使用后会产生碎片。虽然现代文件系统对碎片优化得很好,但在虚拟机这种“磁盘中的磁盘”环境下,碎片化会导致虚拟磁盘文件内部的数据块排列不紧凑,间接影响性能,但更关键的是影响空间回收效率。
  • “脏”数据块未被清零:当虚拟机内的文件系统删除一个文件时,通常只是标记该文件所占用的磁盘块为“可用”,并不会用零去覆盖这些块的内容。VMware的磁盘整理和收缩工具,在识别哪些空间可以回收时,依赖于识别这些全零的数据块。如果块内不是全零,即使逻辑上已被释放,VMware也会认为它仍在使用,从而无法回收。

理解了这三大元凶,我们的瘦身策略就有了清晰的靶心:清理系统垃圾 -> 管理/合并快照 -> 回收虚拟磁盘空间。接下来,我们按照这个顺序,进入实战环节。

3. 第一步:深度清理macOS虚拟机内部

在联系宿主机或VMware工具之前,我们首先要在虚拟机内部进行一场大扫除。目标是尽可能多地将虚拟机内“已删除”文件对应的数据块,变成全零块,为后续的磁盘收缩创造条件。

3.1 使用专业清理工具(推荐首选)

对于大多数用户,我强烈推荐使用专业的第三方清理工具,它们更安全、更全面。我长期使用的是CleanMyMac X(付费,但有试用版)和Onyx(免费)。这里以CleanMyMac X的思路为例,介绍需要清理的模块:

  1. 智能扫描:执行一键式扫描,它会识别系统垃圾、邮件附件、旧iOS备份、开发缓存等。
  2. 系统垃圾:重点清理。这里包括系统缓存、用户缓存、日志、本地化语言包(对你没用的语言)、更新残留等。清理前可以点开详情查看具体是哪些文件。
  3. 邮件附件:如果你不用虚拟机里的邮件App,或者附件已备份,这里可以清理出大量空间。
  4. 废纸篓:别忘了清空虚拟机内的废纸篓。
  5. 大型和旧文件:这个模块能帮你快速找到那些被遗忘在角落的巨型文件(如下载的电影、旧的虚拟机镜像、ISO文件等),手动决定是否删除。

注意:使用任何清理工具时,对于“系统”类别的文件,建议采取保守策略。不要勾选你不完全理解的条目。清理用户目录下的缓存和日志通常是最安全的。

3.2 手动清理命令(给进阶用户)

如果你更喜欢手动控制,或者没有安装清理工具,可以通过终端(Terminal)执行一系列命令。在执行前,请确保你理解每一条命令在做什么。

# 1. 清理用户缓存 (安全) rm -rf ~/Library/Caches/* # 2. 清理系统日志 (相对安全) sudo rm -rf /Library/Logs/* sudo rm -rf ~/Library/Logs/* # 注意:`/var/log`下的某些日志可能需要特定权限或正在被使用,建议使用`sudo log erase --all`来清空日志内容,而不是删除文件本身。 # 3. 清理Xcode衍生数据(如果你是开发者) rm -rf ~/Library/Developer/Xcode/DerivedData rm -rf ~/Library/Developer/Xcode/iOS\ Device\ Support/ # 删除旧版本设备的符号文件 # 4. 清理Homebrew(如果使用) brew cleanup --prune=all # 5. 清理Docker(如果使用) docker system prune -a --volumes

3.3 处理Time Machine本地快照

这是macOS Catalina及以后版本的一个大空间占用源。即使你没有外接备份磁盘,系统也会创建本地快照。

  1. 列出所有本地快照:
    tmutil listlocalsnapshots /
  2. 删除指定的本地快照(将YYYY-MM-DD-HHMMSS替换为实际快照名):
    sudo tmutil deletelocalsnapshots YYYY-MM-DD-HHMMSS
  3. 你也可以暂时禁用本地快照(不建议长期禁用,因为它提供了有用的文件恢复功能):
    sudo tmutil disablelocal
    重新启用使用:
    sudo tmutil enablelocal

完成内部清理后,重启一次macOS虚拟机,让系统状态稳定下来。然后,你可以打开“关于本机”->“存储空间”查看释放了多少空间。但请注意,此时宿主机上虚拟磁盘文件的大小很可能没有任何变化。这是正常的,因为我们的清理只是第一步。

4. 第二步:管理并整合VMware快照

快照是虚拟磁盘膨胀的“放大器”。在进行最终的磁盘收缩前,必须处理好快照。

4.1 评估你的快照状态

首先,在VMware Workstation(或Fusion)的虚拟机设置中,查看“快照管理器”。你会看到一棵快照树。思考以下问题:

  • 这些快照还有用吗?是否只是为了某个已经完成的一次性测试?
  • 你当前处于哪个快照上?还是“当前状态”?
  • 最早的快照创建了多久?它之后你写了多少数据?

4.2 策略一:删除无用快照

对于确定不再需要的快照,直接删除。删除快照是一个磁盘密集型操作,可能会持续几分钟到几小时,取决于快照的大小和磁盘速度。在此期间,不要对虚拟机进行任何操作。

操作方法:在快照管理器中,选中要删除的快照,点击“删除”或“删除快照”。VMware会将该快照的更改合并到父磁盘中。如果删除的是非当前状态的快照,合并后虚拟机的状态不会改变。

重要警告:确保宿主机有足够的剩余磁盘空间(至少大于你要删除的那个快照文件的大小),否则合并过程会失败,可能导致快照链损坏。最稳妥的办法是,在尝试删除任何快照前,先确保宿主机有等同于整个虚拟机磁盘文件大小的空闲空间。

4.3 策略二:整合所有更改(“转到”当前状态)

如果你的目的是永久保存当前虚拟机的状态,并抛弃所有历史快照,那么最彻底的方法是“转到”当前状态。

操作方法:在快照管理器中,选中“当前状态”(通常是最顶部的一个条目),然后选择“转到”。VMware会询问你是否将自所选快照以来的所有更改永久保存到基础磁盘。选择“是”。这个过程实际上会删除所有的快照增量文件,并将所有数据整合到主磁盘文件中。这是进行磁盘收缩前最理想的状态。

执行完快照删除或整合操作后,虚拟磁盘文件(.vmdk)的大小可能依然没变,甚至可能暂时变大(因为合并操作产生了新的数据写入)。别急,关键的最后一步来了。

5. 第三步:核心操作——收缩VMware虚拟磁盘

这是将虚拟机内部释放的空间,真正归还给宿主机的魔法步骤。其原理是:VMware工具会读取虚拟磁盘的每一个数据块,如果发现全是零(即我们之前清理和快照合并后产生的“空白”区域),它就会将这些零块从物理文件中剔除,从而缩小.vmdk文件的大小。

5.1 准备工作:在macOS虚拟机内“置零”空闲空间

为了让VMware工具能识别出可回收的空间,我们必须让macOS系统将所有空闲的存储空间用零填充。这需要在虚拟机内部完成。

  1. 确保磁盘有足够空闲空间:进行置零操作本身需要写入大量数据,因此你的macOS虚拟机必须至少有10-15%的可用空间。如果刚刚清理完,这通常不是问题。
  2. 打开终端(Terminal)
  3. 运行置零命令
    • 如果你的macOS虚拟机使用的是APFS文件系统(macOS High Sierra及以后版本的默认文件系统):
      sudo diskutil secureErase freespace 0 /
      这条命令会向根目录/的所有空闲空间写入一次零。0代表最快速的单次零填充模式,对于我们的目的来说完全足够。
    • 如果你的macOS虚拟机使用的是较旧的HFS+(Core Storage)文件系统:
      # 首先,如果需要,禁用Time Machine的本地快照(避免干扰) sudo tmutil disablelocal # 然后创建一个填充零的大文件,再删除它 dd if=/dev/zero of=/tmp/bigemptyfile bs=1m # 等待命令完成(会持续一段时间,直到磁盘空间满报错) # 完成后删除该文件 rm /tmp/bigemptyfile # 重新启用本地快照(可选) sudo tmutil enablelocal

      注意dd命令会一直写直到磁盘满,这可能需要很长时间,并且会生成一个巨大的临时文件。操作时请留意终端输出。

置零过程会持续一段时间,并且虚拟机磁盘I/O会很高,这是正常现象。完成后,最好正常关闭macOS虚拟机(选择“关机”,而不是“挂起”)。

5.2 执行VMware磁盘收缩

现在,虚拟机已经关机,并且其空闲空间已被零填充。我们回到宿主机(Windows或Linux)进行操作。

  1. 定位VMware磁盘工具

    • Windows (VMware Workstation Pro/Player):工具通常位于安装目录,如C:\Program Files (x86)\VMware\VMware Workstation\vmware-vdiskmanager.exe。但更简单的方法是使用命令行或Workstation自带功能。
    • macOS (VMware Fusion):工具是/Library/Application Support/VMware Fusion/vmware-vdiskmanager或通过Fusion菜单操作。
  2. 方法一:使用VMware Workstation图形界面(推荐)

    • 打开VMware Workstation,确保目标虚拟机已关闭。
    • 在虚拟机库中,右键点击该虚拟机 -> “管理” -> “清理磁盘”。
    • VMware会弹出一个对话框,告诉你它可以回收多少空间。点击“清理”或“压缩”按钮开始。
    • 这个过程会启动一个后台任务,你可以在Workstation底部状态栏看到进度。时间取决于虚拟磁盘大小和需要回收的空间量。
  3. 方法二:使用命令行工具(更通用)

    • 打开宿主机系统的命令行(CMD或PowerShell,以管理员身份运行;在macOS/Linux上是终端)。
    • 切换到虚拟机文件所在目录,或者使用完整路径。
    • 执行收缩命令。命令格式因VMware版本和磁盘类型略有不同,请先查阅官方文档。一个常见的示例如下(用于Workstation):
      # Windows 示例 "C:\Program Files (x86)\VMware\VMware Workstation\vmware-vdiskmanager.exe" -k "你的虚拟机目录\macOS.vmdk" # -k 参数代表收缩(shrink)
    • 对于Fusion,命令类似:
      /Applications/VMware\ Fusion.app/Contents/Library/vmware-vdiskmanager -k ~/Documents/Virtual\ Machines.localized/macOS.vmwarevm/macOS.vmdk

收缩过程同样需要时间,请耐心等待完成。完成后,你会惊喜地发现.vmdk文件的大小显著减小了。

6. 进阶策略与长期维护建议

一次成功的瘦身能解决燃眉之急,但养成良好的使用习惯才能避免问题复发。

6.1 虚拟磁盘类型的选择与转换

  • 厚置备延迟置零 (Thick Provision Lazy Zeroed):创建时即分配全部大小,但物理空间用零填充是“延迟”进行的。性能较好,空间回收简单(因为未使用的部分本来就是零),但初期占用全部空间。
  • 厚置备置零 (Thick Provision Eager Zeroed):创建时即分配并写零填充全部空间。性能最好,常用于企业级环境,但初期占用全部空间且创建慢。
  • 动态分配 (Thin Provision):默认选项。按需增长,不自动收缩。我们遇到的问题主要发生在这种类型上。

建议:如果你的宿主机磁盘空间充足,并且追求更稳定的性能和更简单的维护,可以考虑将磁盘转换为“厚置备”类型。在VMware中,这通常通过“编辑虚拟机设置”->“硬盘”->“实用程序”->“转换”来完成。注意:转换过程需要额外的临时磁盘空间,且耗时较长。

6.2 建立定期维护流程

将虚拟机瘦身作为一项定期(例如每季度或每半年)的维护任务:

  1. 内部清理:运行CleanMyMac X或执行手动清理脚本。
  2. 快照整理:评估并删除过期快照,尽量保持快照链简短,或使用“转到”功能整合。
  3. 磁盘置零与收缩:在虚拟机空闲时(如周末),执行置零和收缩操作。

6.3 将用户数据与系统分离

这是一个从根本上减少系统盘增长压力的方法。在创建虚拟机时,可以额外添加一块虚拟硬盘(比如100GB用于系统,500GB用于数据),并将你的用户文件夹(~/Documents,~/Downloads等)、开发项目、媒体库等重定向到这块数据盘上。这样,系统盘的写入量会大大减少,膨胀速度自然变慢。即使需要做快照,也只需要对系统盘做,数据盘可以设置为“独立-持久”模式,排除在快照之外。

6.4 监控与预警

不要等到宿主机磁盘爆满才行动。可以:

  • 在宿主机上,使用文件夹大小查看工具(如Windows的TreeSize Free,macOS的OmniDiskSweeper)定期检查虚拟机文件目录的大小。
  • 在macOS虚拟机内,开启“存储空间”管理中的“优化存储”建议(自动清空废纸篓、删除看过的影片等),但这只能辅助解决内部问题。

经过以上这一套组合拳,你的macOS虚拟机应该能从臃肿的“空间吞噬者”回归清爽。整个过程最关键的体会是:虚拟机的空间管理是一个主动的过程,而不是被动的反应。理解其工作原理,建立定期维护的习惯,才能让它持续稳定地为你服务,而不是时不时跳出来制造一场存储危机。

← 返回列表