1. 虚拟机磁盘为什么会越用越大用 VMware Workstation 的人基本都会碰到同一个问题虚拟机用着用着宿主机上的那个文件夹就膨胀到几十个 G明明虚拟机里删了一堆东西宿主机上的 vmdk 文件却一点没变小。我自己的主力开发机上有三台虚拟机一台 Ubuntu 做编译环境一台 Windows 10 跑一些只能在 Windows 下用的工具还有一台 CentOS 做服务端测试三台加起来占了快 200G其中至少有一半是虚胖。这个虚胖的根源在于 VMware 的磁盘分配机制。创建虚拟机时通常有两种磁盘模式厚置备Thick Provision和薄置备Thin Provision。Workstation 里对应的是立即分配所有磁盘空间和拆分成多个文件这两个选项。如果你当初勾了立即分配那 vmdk 从创建那一刻起就是固定大小删文件不会让它缩小如果没勾vmdk 会随着写入数据逐步增长但增长容易收缩难——虚拟机内部删除文件后操作系统只是把对应的块标记为可用VMware 并不知道这些块已经没用了所以 vmdk 只增不减。这就引出了清理磁盘的两条主线一是在虚拟机内部把无用数据真正清掉二是让 VMware 知道哪些块可以回收从而压缩 vmdk 文件。很多人只做了第一步发现宿主机空间没变化就以为清理失败了其实是漏了第二步。下面我把整套流程拆开讲从原理到命令到踩坑尽量让你一次搞定。提示本文所有操作以 VMware Workstation Pro 17 为例宿主机为 Windows客户机涵盖 Ubuntu、CentOS、Windows 10。ESXi 环境思路一致但部分命令和界面不同我会在对应位置标注。2. 清理前的准备工作与风险认知2.1 先搞清楚你的磁盘是哪种模式动手之前必须先确认磁盘类型否则后面做的压缩可能完全无效。在 VMware Workstation 里选中虚拟机右键设置找到硬盘看右侧的磁盘实用工具或者直接看虚拟机目录下的文件。判断方法很简单如果目录下只有一个大的.vmdk文件且大小固定不变那是厚置备单文件。如果有xxx.vmdk加上一堆xxx-s001.vmdk、xxx-s002.vmdk这样的分片文件那是拆分模式通常也是薄置备。如果只有一个.vmdk且会随使用增长那是薄置备单文件。我一般推荐薄置备因为省空间但代价就是需要定期清理。厚置备的好处是性能稳定、不会碎片化但空间一旦分配就收不回来除非用后面的方法转换。2.2 快照是磁盘膨胀的头号元凶在讲清理之前必须先说快照。快照会让磁盘空间成倍增长因为每个快照都会保存一份差异磁盘delta disk你后续的所有写入都记录在差异盘里原来的基础盘保持不变。如果你有多个快照差异盘会层层叠加空间占用非常夸张。我见过最极端的案例一台 40G 的虚拟机因为累积了 7 个快照实际占用 180G。所以清理磁盘的第一步永远是检查并清理快照。在 VMware Workstation 里菜单栏虚拟机 → 快照 → 快照管理器能看到所有快照的时间线。如果这些快照你都不需要了直接删除。注意删除快照不是删除虚拟机当前状态而是把快照里的数据合并回基础盘这个过程可能比较慢取决于差异盘大小别中途强制关闭。注意删除快照时如果提示空间不足先确保宿主机有足够剩余空间因为合并过程需要临时空间。合并完成后虚拟机目录下那些-000001.vmdk之类的差异盘会消失空间会释放一部分。2.3 备份永远不嫌多任何涉及磁盘的操作都有风险尤其是后面的vmware-vdiskmanager压缩和磁盘碎片整理。我的习惯是清理前先把整个虚拟机目录复制一份到移动硬盘或者另一块盘。虚拟机目录通常就是那几个文件.vmx配置文件、.vmdk磁盘、.nvram、.vmsd等。整个文件夹拷走出问题直接换回来比任何修复都靠谱。如果你嫌整个拷贝太占空间至少把.vmx和.vmsd备份一下这两个文件很小但记录了虚拟机的硬件配置万一磁盘操作把配置搞乱了还能对照恢复。3. 虚拟机内部清理把垃圾真正清掉3.1 Linux 客户机的清理要点Linux 下清理磁盘核心是找出大文件和无用缓存。我常用的组合是du、find和包管理器自带的清理命令。先看整体占用df -h du -sh /* 2/dev/null | sort -rh | head -20第一条看各分区使用率第二条列出根目录下各一级目录的大小并排序。通常/var、/usr、/home、/tmp是重灾区。/var下面最常见的是日志和包缓存# 查看日志占用 du -sh /var/log/* # 清理 systemd journal 日志只保留最近 3 天 journalctl --vacuum-time3d # 清理 apt 缓存Ubuntu/Debian apt-get clean apt-get autoclean # 清理 yum/dnf 缓存CentOS/RHEL yum clean all dnf clean all/tmp目录可以直接清空但注意有些程序运行时会用临时文件最好在关机前清理rm -rf /tmp/*还有一个容易被忽略的地方是旧内核。Ubuntu 上每次内核更新都会保留旧版本时间长了/boot和/usr/src会堆积很多。查看已安装内核dpkg --list | grep linux-image确认当前运行的内核版本uname -r然后删掉不用的旧内核apt-get purge linux-image-5.15.0-xx-genericCentOS 上用package-cleanup --oldkernels --count2保留最近两个内核。3.2 Windows 客户机的清理要点Windows 虚拟机的空间大头通常是系统更新缓存、休眠文件、页面文件、临时文件、旧系统备份。最直接的是用系统自带的磁盘清理右键 C 盘 → 属性 → 磁盘清理 → 清理系统文件。勾选Windows 更新清理、以前的 Windows 安装、临时文件等。这一步能释放几个 G 到几十个 G 不等。休眠文件hiberfil.sys往往和内存一样大如果虚拟机不需要休眠功能直接关掉powercfg -h off页面文件pagefile.sys也可以调整但建议保留只是可以设小一点或者移到别的盘。如果虚拟机内存是 8G页面文件默认可能也是 8G 左右。另外 Windows 的WinSxS目录会随着更新越来越大可以用Dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase这个命令会清理组件存储里的旧版本但执行后无法卸载已安装的更新权衡一下再用。3.3 用零填充把空闲块标记出来这是最关键的一步也是最多人漏掉的一步。虚拟机内部删除文件后那些块在文件系统层面是空闲的但 VMware 不知道。我们需要用零写满所有空闲空间这样 VMware 在压缩时就能识别出这些块是全零从而安全回收。Linux 下用dd或者zerofree# 方法一dd 写零文件再删除 dd if/dev/zero of/zero.fill bs1M rm -f /zero.fill syncdd会一直写到磁盘满报 No space left on device 是正常的然后删掉这个文件。注意如果磁盘是 ext4 且挂载了discard选项或者用了 SSD可能不需要这步但为了保险还是做一下。更优雅的方式是用zerofree它只填充空闲块速度更快但需要把分区卸载或者以只读挂载# 安装 apt-get install zerofree # 进入单用户模式或从 Live CD 启动卸载分区后执行 zerofree /dev/sda1Windows 下没有直接的dd但可以用sdeleteSysinternals 工具sdelete -z C:-z参数就是写零清理空闲空间。这个工具微软官方提供下载后放到虚拟机里执行即可。执行时间取决于磁盘大小和空闲空间可能比较久耐心等。提示写零操作会让虚拟机磁盘文件暂时膨胀到接近满盘所以宿主机必须有足够剩余空间。比如虚拟机分配了 60G实际用了 30G写零过程中 vmdk 可能涨到接近 60G压缩后再降下来。宿主机空间紧张的话先清理宿主机。4. 用 vmware-vdiskmanager 压缩磁盘4.1 工具在哪、怎么用vmware-vdiskmanager是 VMware Workstation 自带的命令行工具Windows 下在安装目录通常是C:\Program Files (x86)\VMware\VMware Workstation\vmware-vdiskmanager.exeLinux 宿主机上一般在/usr/bin/vmware-vdiskmanager或/usr/lib/vmware/bin/下。它的核心功能包括压缩、碎片整理、扩容、转换磁盘类型。我们清理磁盘主要用两个参数-ddefragment碎片整理和-kshrink压缩。基本语法vmware-vdiskmanager -k 路径\虚拟机磁盘.vmdk4.2 操作顺序先整理再压缩正确的顺序是先碎片整理再压缩。碎片整理把分散的块集中压缩才能更高效地回收空间。# 第一步碎片整理 vmware-vdiskmanager -d D:\VMs\Ubuntu\Ubuntu.vmdk # 第二步压缩 vmware-vdiskmanager -k D:\VMs\Ubuntu\Ubuntu.vmdk执行前必须关闭虚拟机不是挂起是完全关机。挂起状态下磁盘文件被锁定工具会报错。Windows 下如果路径有空格记得加引号。执行过程会有进度提示压缩大磁盘可能十几分钟到半小时。4.3 压缩能回收多少空间压缩的效果取决于你之前写零是否彻底。我实测过几台虚拟机压缩前 vmdk压缩后 vmdk回收比例Ubuntu 22.04开发环境58G32G45%Windows 10办公76G41G46%CentOS 7服务测试43G25G42%可以看到只要写零做到位回收 40% 以上很常见。如果压缩后几乎没变化八成是写零没做或者磁盘是厚置备模式。4.4 厚置备转薄置备如果你的磁盘是厚置备-k压缩基本无效因为厚置备的块是预分配的。这时候需要转换磁盘类型。vmware-vdiskmanager支持-r参数转换vmware-vdiskmanager -r source.vmdk -t 0 target.vmdk其中-t后面的数字代表磁盘类型0单文件薄置备1拆分薄置备2预分配单文件3预分配拆分4精简预分配拆分ESXi 用转换会生成一个新的 vmdk原来的保留。转换完成后需要在虚拟机设置里把硬盘指向新文件确认能正常启动后再删旧的。这个过程比较耗时而且需要额外空间存放新磁盘宿主机空间要留够。注意转换磁盘类型前务必确认虚拟机内没有快照有快照的磁盘不能直接转换必须先删除快照。5. 图形界面下的清理操作5.1 磁盘实用工具里的压缩选项不想敲命令的话VMware Workstation 的图形界面也提供了压缩功能。选中虚拟机 → 设置 → 硬盘 → 磁盘实用工具 → 压缩。这个按钮背后调用的就是vmware-vdiskmanager -k效果一样。但图形界面的压缩不会帮你做碎片整理也不会帮你写零。所以如果你只是点一下压缩效果往往不理想。我的建议还是走命令行或者至少先在虚拟机里写零再用图形界面压缩。5.2 清理磁盘的向导较新版本的 Workstation 在虚拟机菜单下有管理 → 清理磁盘会弹出一个向导引导你选择要清理的磁盘然后执行压缩。这个向导本质上也是调用同一个工具适合不熟悉命令行的用户。不过向导有个限制它只能处理当前关机状态的虚拟机而且对拆分磁盘的支持有时候会出问题。我遇到过拆分磁盘压缩到一半报错的情况最后还是用命令行分片处理才搞定。5.3 快照管理器的空间回收前面提过快照这里再强调一下操作路径。快照管理器里可以删除单个快照也可以删除所有快照。删除所有快照会把所有差异盘合并回基础盘这个过程会释放大量空间但耗时可能很长。合并完成后建议再做一次碎片整理和压缩因为合并过程可能产生碎片。我一般的顺序是删快照 → 开机清理内部垃圾 → 关机写零 → 碎片整理 → 压缩。这一套下来基本能把虚拟机瘦回刚创建时的水平。6. 常见问题与排查技巧实录6.1 压缩时报磁盘被锁定怎么办最常见的原因是虚拟机没完全关机或者 VMware 的后台进程还在占用文件。解决步骤确认虚拟机是关机状态不是挂起或休眠。关闭 VMware Workstation 主界面。打开任务管理器结束所有vmware-vmx.exe、vmware.exe进程。如果还不行重启宿主机确保没有残留进程。有时候是杀毒软件在扫描 vmdk 文件导致锁定临时关闭杀毒软件的实时防护再试。6.2 压缩后空间没变化排查顺序确认磁盘是薄置备厚置备压缩无效。确认虚拟机内做了写零操作没写零的话 VMware 无法识别空闲块。确认没有快照有快照时压缩的是基础盘差异盘不受影响。确认压缩的是正确的 vmdk 文件拆分磁盘要指定主文件不带-s001后缀的那个。6.3 写零时提示空间不足dd写零会占满整个空闲空间如果宿主机剩余空间不够vmdk 涨到一半就失败了。解决办法先清理宿主机腾出至少等于虚拟机分配大小的空间。或者分批写零比如每次写 5G删掉再写但这样压缩效果会打折扣。用zerofree替代dd它只填充空闲块不会让 vmdk 膨胀太多。6.4 虚拟机启动后黑屏或进不去系统这通常是磁盘操作后引导记录或文件系统出了问题。排查检查虚拟机设置里硬盘是否还指向正确的 vmdk。用系统安装 ISO 启动进入救援模式检查文件系统fsck /dev/sda1。如果是引导问题用grub-install或bootrec /fixmbrWindows修复。我踩过一次坑转换磁盘类型后忘了改虚拟机设置启动时找不到磁盘黑屏。改回正确路径就好了。6.5 常见问题速查表问题现象可能原因解决方法压缩报磁盘锁定虚拟机未关机/进程残留关机、结束 vmware-vmx 进程压缩后空间不变厚置备/未写零/有快照转薄置备、写零、删快照写零空间不足宿主机剩余空间不够清理宿主机或改用 zerofree启动黑屏磁盘路径错误/引导损坏检查设置、fsck、修复引导压缩中途报错拆分磁盘/磁盘损坏分片处理、检查磁盘完整性快照删除很慢差异盘过大耐心等待勿强制关闭6.6 几个我踩过的坑第一个坑是在挂起状态下压缩。有次图省事虚拟机挂起就直接跑vmware-vdiskmanager -k结果报错不说还把挂起状态搞坏了最后只能丢弃挂起状态重新开机。第二个坑是写零后忘了 sync。dd写完删掉文件如果没执行sync数据可能还在缓存里VMware 压缩时读到的还是旧数据压缩效果很差。养成写完就sync的习惯。第三个坑是拆分磁盘只压缩了主文件。拆分磁盘有-s001、-s002等分片vmware-vdiskmanager处理主文件时会自动处理所有分片但如果你手动指定了某个分片就会出错。记住只指定不带分片后缀的主文件名。第四个坑是宿主机磁盘碎片。虚拟机 vmdk 在宿主机上如果碎片严重压缩和整理都会很慢。定期对宿主机做磁盘碎片整理机械硬盘或者 TRIMSSD能明显提升虚拟机磁盘操作速度。7. 日常维护习惯与自动化思路清理磁盘不是一劳永逸的事养成习惯比事后补救更重要。我现在的做法是每台虚拟机每月做一次内部清理每季度做一次完整压缩。内部清理包括清日志、清缓存、清临时文件几分钟搞定完整压缩放在周末反正不影响工作。Linux 虚拟机可以写个简单的清理脚本用 cron 定期执行#!/bin/bash # clean_vm.sh journalctl --vacuum-time7d apt-get clean rm -rf /tmp/* find /var/log -name *.gz -mtime 30 -deleteWindows 虚拟机可以用任务计划程序定期跑磁盘清理和sdelete -z但sdelete比较耗时建议手动执行。另外创建虚拟机时就规划好磁盘大小和类型能省很多事。我现在的习惯是开发环境给 60G 薄置备办公环境给 80G 薄置备服务测试给 40G 薄置备。薄置备虽然需要定期清理但空间利用率高适合宿主机空间有限的场景。如果宿主机空间充足且追求性能稳定厚置备也不是不行只是要接受它不会缩小的现实。最后分享一个小技巧如果你有多台虚拟机可以把它们的清理时间错开避免同时压缩导致宿主机 IO 爆满。我一般周五晚上压缩一台周六压缩另一台周日留给宿主机自己做维护。这样既不影响工作又能保持磁盘整洁。