简介:这份文档面向 VMware 虚拟化运维人员与存储管理员,聚焦 ESXi 环境下精简磁盘(Thin)空间无法自动释放的常见痛点,给出可落地的回收思路与操作参考。资源包内仅含 1 个 docx 文件,约 408KB,以图文步骤形式记录两种回收方案:一是借助 SDelete 清理 Windows 空闲空间后,通过 SSH 登录 ESXi 主机执行 vmkfstools 回收 vmdk 空间;二是利用 Storage VMotion 在线迁移,将磁盘格式切换为厚置备延迟归零再迁回 Thin,实现空间释放。内容结合 Server2012R2 实测场景,展示磁盘实际占用与 VMDK 占用不一致的排查过程,并说明停机与在线两种方式的适用条件。目前已有 2000 余人学习,适合需要处理精简卷空间浪费、优化存储利用率的运维人员参考。
1. 精简磁盘空间回收:为什么删了文件虚拟机还是喊饿
在 VMware Workstation 里跑 Windows 或 Linux 虚拟机的人,几乎都遇到过这个场景:客户机里明明删掉了几十 GB 的日志、缓存、旧镜像,df -h或资源管理器看着是空出来了,可宿主机上那个.vmdk文件纹丝不动,硬盘照样被吃掉。这不是玄学,而是虚拟磁盘的工作方式决定的——客户机操作系统只知道自己有一块「物理盘」,它把块标记为空闲,但 VMware 看到的仍是当初分配出去的那片扇区。所谓精简磁盘空间回收,就是让客户机把「哪些块已经没用了」这件事告诉 VMware,再由 VMware 把这些块在宿主机文件里真正释放掉。它解决的是虚拟磁盘只涨不缩的顽疾,适合长期跑测试环境、做快照堆积、或者把虚拟机当开发机天天写日志的人。搞懂这条链路,你的宿主机才能把空间还回来。
2. 先分清三种磁盘格式:回收能不能做,开局就定了
2.1 厚置备、精简置备与预分配的区别
VMware Workstation 创建虚拟磁盘时,常见的有这么几类:预分配(厚置备)会一次性把整块磁盘大小写到宿主机文件里,比如你给 100 GB,宿主机立刻少 100 GB;精简置备(thin)则按需增长,用多少涨多少。回收这件事,本质上只对精简置备有意义——厚置备的块从一开始就全占着,客户机删文件不会让宿主机文件变小,除非你做磁盘压缩把它转成精简。
判断当前磁盘属于哪种,最直接的办法是看.vmdk文件的实际大小和虚拟机设置里标称容量的差距。如果标称 100 GB、实际文件只有 30 GB,那基本就是精简置备,回收有戏;如果实际文件就是 100 GB 左右,那要么是预分配,要么是精简盘已经涨满了。
提示:回收操作前先关机或至少确保没有正在写入的快照,带快照的磁盘回收经常只回收了个寂寞。
2.2 回收链路:客户机标记、VMware Tools 传递、宿主机落盘
完整的回收链路分三段。第一段在客户机内部,操作系统把删除的块标记为空闲,但这一步只是逻辑标记;第二段靠 VMware Tools 里的驱动或后台服务,把这些空闲块信息收集起来;第三段由 VMware 在宿主机侧执行压缩,把空闲块对应的宿主机文件区域真正释放。任何一段断了,回收都会失败。
这也是为什么很多人装了 VMware Tools 却还是回收不了——Tools 装了不等于相关服务在跑,也不等于客户机文件系统支持这种「空洞传递」。NTFS、ext4 这类主流文件系统支持得比较好,一些老旧的 FAT 或者加密卷就经常掉链子。
2.3 用命令行确认磁盘当前状态
在动手之前,先在宿主机上把虚拟机的磁盘信息摸清楚。Windows 宿主机可以用vmware-vdiskmanager,Linux 宿主机同样有这个工具,路径一般在 VMware 安装目录下。
# 查看虚拟磁盘详细信息,确认类型和当前占用 vmware-vdiskmanager -i "D:\VMs\Win11Dev\Win11Dev.vmdk" # 输出里重点关注 type 字段: # "growable" 表示精简置备,可以回收 # "preallocated" 表示厚置备,需要先转换-i是查询信息,不会改动任何东西,放心跑。输出里的type决定了你后面走哪条路:growable直接进回收流程,preallocated得先用-r转成精简再谈回收。这一步别省,我见过太多人上来就压缩,结果对着一个厚置备盘折腾半天,宿主机空间一点没变。
3. 客户机侧准备:让空闲块真正「空」出来
3.1 Windows 客户机的清理与碎片整理顺序
Windows 客户机回收失败,十有八九是顺序搞反了。正确顺序是:先清理无用文件,再做碎片整理,最后才触发回收。碎片整理会把分散的空闲块聚拢,让后续的回收更彻底;如果先回收再整理,整理过程又会产生新的碎片,等于白干。
清理时重点盯这几类:C:\Windows\Temp、用户目录下的AppData\Local\Temp、各种包管理器的缓存(npm、pip、NuGet)、旧的系统还原点和 Windows 更新缓存。Windows 更新缓存尤其能吃空间,用系统自带的磁盘清理勾上「Windows 更新清理」往往能腾出好几个 GB。
# 以管理员身份运行,清理更新缓存和临时文件 Dism.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase # 清理系统临时目录 Remove-Item -Path "$env:TEMP\*" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "C:\Windows\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue/StartComponentCleanup清理被取代的组件版本,/ResetBase会重置更新基线,代价是之后无法卸载已安装的更新——测试机可以这么干,生产机要谨慎。清理完记得重启一次,让系统把删除操作彻底落盘,再进行碎片整理。
3.2 Linux 客户机的 TRIM 与零填充
Linux 这边思路类似,但工具不同。ext4 支持fstrim,前提是虚拟磁盘控制器支持 discard 传递。VMware 的虚拟 SCSI 控制器在较新版本里支持这个特性,但需要客户机内核和 Tools 配合。
# 先看文件系统是否支持 discard sudo fstrim -v / # 如果报 "the discard operation is not supported", # 说明控制器或文件系统没开这个能力,改用零填充方案 sudo dd if=/dev/zero of=/zero.fill bs=1M status=progress sudo rm -f /zero.fill sudo syncfstrim -v /会告诉文件系统把空闲块标记出来,-v输出回收了多少字节。如果这条路走不通,就用dd写一个占满剩余空间的大文件再删掉——这个操作会把所有空闲块用零覆盖一遍,VMware 后续压缩时就能识别出这些全零块并释放。bs=1M是块大小,status=progress让你看到进度,别用太小的块,否则慢得让人想砸键盘。
注意:零填充会临时占满磁盘,确保宿主机有足够空间承接这个峰值,别在宿主机快满的时候干这事。
3.3 确认 VMware Tools 相关服务在跑
回收依赖 Tools 的后台能力,光装了不够,得确认服务活着。Windows 客户机看服务列表里的VMware Tools Service和VMware 磁盘挂载相关项;Linux 客户机用systemctl status vmtoolsd查。
# Linux 客户机检查 Tools 服务状态 systemctl status vmtoolsd # 如果没跑,启动并设为开机自启 sudo systemctl enable --now vmtoolsd服务没起来,客户机标记的空闲块信息就传不出去,宿主机侧自然无从回收。这一步是很多「我明明清理了却没用」的根因,排查时优先看。
4. 宿主机侧执行:压缩命令与参数怎么调
4.1 关机后用 vdiskmanager 压缩
最稳妥的回收方式是在虚拟机关机状态下,用vmware-vdiskmanager做压缩。关机是为了避免写入干扰,压缩过程中如果有新数据落盘,结果会不一致。
# 关机后执行压缩,-k 表示收缩磁盘 vmware-vdiskmanager -k "D:\VMs\Win11Dev\Win11Dev.vmdk" # 如果磁盘是厚置备,先转精简再压缩 vmware-vdiskmanager -r "D:\VMs\Win11Dev\Win11Dev.vmdk" -t 0 "D:\VMs\Win11Dev\Win11Dev-thin.vmdk" vmware-vdiskmanager -k "D:\VMs\Win11Dev\Win11Dev-thin.vmdk"-k是收缩,它会扫描磁盘里的空闲块并释放。-r是转换,-t 0指定目标类型为精简置备(0 代表 growable)。转换会生成一个新文件,原文件保留,确认新盘能用之后再删旧的。转换过程可能很久,100 GB 的盘在机械硬盘上跑一两个小时很正常,别以为卡死了。
4.2 图形界面里的磁盘压缩入口
不想敲命令的话,VMware Workstation 的图形界面也提供了压缩入口。选中虚拟机,进「虚拟机设置」→「硬盘」→「磁盘实用工具」→「压缩」。这个入口底层调的还是同一套逻辑,适合偶尔用一次的人。但要注意,图形界面的压缩按钮在某些版本里对厚置备盘是灰的,这时候还是得回到命令行转换。
4.3 压缩前后对比与验证
压缩完别急着高兴,先验证。对比压缩前后.vmdk文件的大小,再看虚拟机能不能正常启动、数据有没有丢。
# 压缩前后各跑一次,对比文件大小 ls -lh "D:\VMs\Win11Dev\Win11Dev.vmdk" # 启动虚拟机后,在客户机里确认文件系统正常 # Linux: df -h # Windows: 资源管理器看各分区容量如果压缩后文件没怎么变小,常见原因是客户机里空闲块没被正确标记(回到第 3 章检查),或者磁盘本身就没多少可回收空间。如果压缩后虚拟机起不来,多半是压缩过程中文件损坏,这时候快照或备份就是你的后悔药——所以压缩前做一次完整备份,这个习惯能救命。
5. 避坑与排查:回收失败的五个典型现场
5.1 压缩后宿主机空间没变化
现象:命令跑完提示成功,但宿主机可用空间几乎没动。原因通常是磁盘本身是厚置备,或者客户机空闲块没标记。解决:先用-i确认磁盘类型,厚置备先转精简;再回客户机确认清理和零填充做到位,Tools 服务在跑。
5.2 带快照的虚拟机压缩报错
现象:压缩时提示磁盘有快照或无法锁定。原因:快照文件依赖基础磁盘,压缩会破坏快照链。解决:先在快照管理器里删除或合并快照,再关机压缩。如果快照很重要,先克隆一份出来单独处理。
5.3 Linux 客户机 fstrim 报不支持
现象:fstrim -v /返回不支持的操作。原因:虚拟 SCSI 控制器没开 discard 传递,或文件系统挂载时没启用相关选项。解决:改用dd零填充方案,或者检查虚拟机设置里 SCSI 控制器类型,换成支持 discard 的型号后重启再试。
5.4 压缩过程卡住或极慢
现象:压缩进度长时间不动。原因:宿主机磁盘本身碎片严重,或虚拟磁盘文件过大。解决:先给宿主机做一次碎片整理,确保宿主机有足够连续空间;大磁盘分批处理,别指望一次搞定。机械硬盘上慢是正常的,换 SSD 会快很多。
5.5 压缩后客户机文件系统报错
现象:虚拟机启动后提示文件系统损坏或需要检查。原因:压缩过程中断电、宿主机空间不足导致写入中断。解决:用客户机自带的文件系统检查工具修复(Windows 的chkdsk、Linux 的fsck),修复不了就从备份恢复。这也是为什么压缩前备份不能省。
6. 把回收做成习惯:自动化脚本与长期维护
回收不是一锤子买卖,虚拟机用久了空间又会涨回去。与其每次手动折腾,不如把它做成定期维护。我的做法是给每台长期使用的虚拟机写一个维护脚本,客户机侧负责清理和零填充,宿主机侧负责压缩,两边配合。
#!/bin/bash # 客户机侧维护脚本,放在 Linux 客户机里定期跑 set -e echo "清理包管理器缓存..." sudo apt-get clean sudo apt-get autoremove -y echo "清理日志..." sudo journalctl --vacuum-time=7d echo "零填充空闲块..." sudo dd if=/dev/zero of=/zero.fill bs=1M status=progress || true sudo rm -f /zero.fill sudo sync echo "客户机侧完成,请在宿主机执行压缩"这个脚本的逻辑是:先清缓存和旧日志,再用零填充把空闲块覆盖,最后同步落盘。journalctl --vacuum-time=7d只保留最近七天的日志,按需调整天数。|| true是为了让dd写满磁盘报错时不中断脚本——写满本来就是预期行为。
宿主机侧对应一个压缩脚本,关机后调用:
#!/bin/bash # 宿主机侧压缩脚本,Linux 宿主机示例 VMDK="/path/to/your/vm/disk.vmdk" echo "压缩前大小:" ls -lh "$VMDK" vmware-vdiskmanager -k "$VMDK" echo "压缩后大小:" ls -lh "$VMDK"两个脚本配合,每月跑一次,虚拟机的空间占用就能控制在一个合理范围。Windows 客户机的话,把清理部分换成 PowerShell 的清理命令,零填充用cipher /w:C或者写零文件的方式,思路完全一样。
一个我踩过的坑:早期我图省事,在虚拟机运行状态下直接压缩,结果压缩到一半客户机还在写日志,压缩完文件大小没变多少,还差点把文件系统搞坏。从那以后我给自己定了死规矩——压缩前必须关机,必须备份,必须确认 Tools 服务正常。这三条看着啰嗦,但省下的返工时间远超这点准备成本。回收这件事,慢就是快,稳就是省。希望帮到你。
本文还有配套的精品资源,点击获取