虚拟机删除文件后宿主机磁盘空间却没有释放,这是虚拟磁盘“只增不减”的特性导致的,解决办法是执行虚拟磁盘的“碎片整理”和“压缩/收缩”操作。
你可能会遇到这种情况:在虚拟机里删了好几个G的日志文件,回到宿主机一看,磁盘剩余空间纹丝不动,别慌,这不是文件没删干净,而是虚拟机磁盘文件的“欺骗性”在作祟。
为什么虚拟机删了文件,磁盘空间却不释放?
要解决空间问题,得先搞清楚病根,虚拟机运行时,所有写入的数据都会被塞进一个或多个大文件里,比如VMware的.vmdk文件,VirtualBox的.vdi文件,Hyper-V的.vhdx文件。
当你在虚拟机内部删除文件时,系统只是把磁盘上的数据块标记为“可覆盖”,并没有把物理空间还给宿主机,虚拟磁盘文件依然保持着“虚胖”的状态,只有当你把那些空闲的数据块彻底清空、压缩,宿主机才可能真正回收这部分空间。
业界常见的说法是:Linux用fstrim或zerofree,Windows用碎片整理或SDelete,目的都是把空闲块归零,给后续的压缩操作创造条件。
VMware虚拟机清理后如何彻底释放磁盘空间?
VMware Workstation和ESXi在操作路径上略有差异,但核心思路一致:先整理,再压缩。
第一步:在虚拟机内部“归零”空闲空间
- Windows虚拟机:下载微软官方的Sysinternals工具,用管理员身份运行命令提示符,进入SDelete所在目录,执行
sdelete -z C:,这一步会让所有空闲磁盘块变为零,这个过程需要一段时间,界面看起来像是卡住了,实际上是在后台干活,耐心等待进度到100%即可。 - Linux虚拟机:如果你的内核较新,可以直接执行
fstrim -v /命令,对根分区进行TRIM操作,如果提示不支持,则需要安装zerofree工具,在单用户模式或Live CD环境下,对未挂载的分区执行zerofree /dev/sda1。
第二步:在宿主机执行压缩命令
- VMware Workstation:关闭虚拟机,打开命令提示符,切换到VMware安装目录(默认是 C:Program Files (x86)VMwareVMware Workstation),执行
vmware-vdiskmanager -k "你的虚拟机磁盘路径.vmdk"。 - ESXi主机:通过SSH登录,找到虚拟机的vmdk文件路径,执行
vmkfstools -K 你的虚拟机磁盘路径.vmdk在ESXi 6.5及以上版本中,收缩操作需要先使用vmkfstools --punchzero来处理零块,行业共识认为,ESXi的收缩操作对存储阵列的Trim特性有较高要求,如果你用的是机械硬盘直通,效果可能不太明显。 - 关键点:如果虚拟机有快照,需要先删除所有快照,快照会把数据分散到多个delta文件中,不合并快照的话,无论怎么压缩都不会有效果。
VirtualBox和Hyper-V怎么处理空间不释放的问题?
除了VMware,VirtualBox和Hyper-V也是很多朋友在用的方案,它们的处理逻辑类似,但命令不同。
VirtualBox的“瘦身”方案
VirtualBox使用的是.vdi文件,同样有“只增不减”的毛病。
- 归零操作:跟VMware一样,Windows虚拟机用SDelete,Linux虚拟机用fstrim。
- 压缩操作:关闭虚拟机后,打开命令提示符,执行
VBoxManage modifyhd "你的虚拟磁盘路径.vdi" --compact,这个命令会重建整个vdi文件,把里面的空白部分剔除掉,注意,必须在虚拟机完全关机的状态下执行,休眠状态也不行。
Hyper-V的“在线收缩”功能
Hyper-V的.vhdx文件是这几款里唯一支持“原地收缩”的,但前提是你需要开启“虚拟化”选项。
- 打开Hyper-V管理器,右键点击虚拟机,选择“设置”,在“硬盘驱动器”里勾选“启用虚拟硬盘压缩”。
- 之后在虚拟机内部,只要有新的删除操作,Hyper-V会自动尝试在线压缩空间,据统计,这种动态收缩机制能有效避免vmware虚拟机清理磁盘空间没释放的问题在下一代系统上大面积出现,但对磁盘IOPS有一定的额外消耗。
- 如果是离线操作,管理员也可以在PowerShell里执行
Optimize-VHD -Path 你的虚拟磁盘路径.vhdx -Mode Full,想象一下这样一个场景:你的C盘已经告急,红条刺眼,而这个命令能把.vhdx文件里所有标记为“空闲”的簇彻底抹掉,让文件大小回到几周前的水平。
实战排雷:为什么按教程操作了,空间还是没释放?
很多时候,你明明执行了压缩命令,但空间就是没变,这通常不是操作问题,而是“表面干净”迷惑了你。
- 检查是否有隐藏的删除文件:虚拟机的回收站是否已经清空?虚拟机里的系统还原点是否占用了大量空间?这些在虚拟机内部是“被占用”的,压缩工具当然不会去动它们。
- 检查磁盘碎片整理状态:如果虚拟机磁盘碎片太多,即便执行了归零操作,也可能存在大量非零数据块,建议先在虚拟机里执行完整的磁盘碎片整理,然后再做归零和压缩。
- 检查vmdk文件的类型:如果你创建的是“独立持久化”磁盘,压缩命令会直接报错,只有“非独立”或“Thin”类型的磁盘才支持在线收缩。
vmware-vdiskmanager命令在较新版本的VMware Workstation 17 Pro中已被标记为“已弃用”,但依然可用,如果你用的OVF模板导入的虚拟机,磁盘可能存在“拆分”模式,需要先用vmware-vdiskmanager -r把磁盘重新整合成单文件,再执行压缩。
如何从根本上避免虚拟机磁盘空间只增不减?
与其每次等磁盘满了才去折腾,不如在创建虚拟机时就做好规划。
- 优先使用动态分配磁盘:不要一开始就分配固定大小,选择“动态分配”或“精简配置”,这样物理磁盘占用会随着虚拟机内部数据增加而缓慢增长,删除文件后,只要及时压缩,空间就能有效回收。
- 定期执行“零填充”任务:在虚拟机内部设置一个计划任务,每个季度执行一次SDelete或fstrim,然后把压缩操作记在运维日历上,不用等提示“磁盘空间不足”才想起这回事。
- 监控宿主机实际容量:别只看虚拟机内部文件管理器显示的数据,要盯着宿主机上那个vmdk文件的实际大小,你可以用
ls -lh或磁盘管理工具查看,如果发现虚拟磁盘文件比虚拟机内已用的数据大了好几倍,说明空间泄漏已经相当严重了。
Q&A:关于虚拟机清理磁盘的常见疑问
问:为什么我在Windows虚拟机里用了SDelete,再执行压缩,空间还是没变?
答:检查SDelete是否执行成功,需要看到提示“Cleanup complete”,如果中途报错“Access Denied”,多半是没有管理员权限,SDelete对NTFS压缩卷或加密卷无效,需要先取消文件压缩属性,还有一点,如果虚拟机的虚拟内存(页面文件)和休眠文件占用了较大空间,那部分属于系统托管文件,常规归零操作无法合并。
问:VMware和VirtualBox的压缩命令有什么区别?
答:VMware用的是 vmware-vdiskmanager -k,只适用于停止状态下的虚拟机,且要求磁盘为“非独立”模式,VirtualBox用的是 VBoxManage modifyhd --compact,同样要求虚拟机处于关机状态,两者在操作前,都必须确保虚拟机内部的空闲空间已经被写入零字节,否则压缩命令跑完,文件体积几乎不会变化。
问:在ESXi里面执行了vmkfstools -K,为什么宿主机数据存储的空间使用量不降反升?
答:ESXi的 vmkfstools -K 命令会先做一次空间回收,但如果底层存储不支持自动回收精简磁盘,数据存储会先保留原有块,再尝试写入新块,导致瞬时空间占用量升高,这种情况下,需要在存储侧手动执行一次“数据存储重新分配”操作,在vSphere Client中选中数据存储,点击“操作-重新分配”即可触发底层回收流程,如果虚拟机所在的数据存储是厚置备延迟置零模式,空间不会在虚拟机内释放,这可能是原因所在。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/763364.html





