压缩Hyper-V的虚拟硬盘(VHD/VHDX)释放空间
针对你的情况,核心问题在于Hyper-V的虚拟硬盘(VHD/VHDX)具有“只增不减”的特性。即使你在虚拟机(Ubuntu)内部删除了大量文件,物理机上的VHD文件依然保持着膨胀后的大小,不会自动释放空间。
目前的困境是:
- 物理机(宿主机)D盘:剩余空间 43.4 GB。
- 虚拟机(客户机)内部:已删除文件,显示有大量空闲空间。
- 目标:对虚拟机文件进行压缩(精简),释放物理机D盘空间。
结论: 在D盘剩余43.4 GB的情况下,只要你的虚拟机VHD文件不是特别巨大(例如超过100GB),通常是可以进行压缩处理的。
以下是具体的操作步骤,分为“零填充”和“压缩”两个阶段。
第一阶段:在虚拟机(Ubuntu)内部操作
这一步的目的是告诉硬盘:“这些块现在是空的,可以被回收”。
-
安装
zerofree工具(推荐方式) 在Ubuntu终端中执行:sudo apt-get update sudo apt-get install zerofree -
执行零填充 由于
zerofree不能在挂载(读写)状态下运行根分区,你需要进入恢复模式或使用Live CD。但有一个更简单的方法,使用dd命令(虽然不如zerofree彻底,但在运行中可用):方法 A:使用 dd 命令(无需重启,操作简单) 在Ubuntu终端执行以下命令,它会在磁盘空闲处写入全0文件,填满磁盘后再删除。
# 这一步会占用所有剩余空间,直到报错“设备上没有空间”,这是正常的 sudo dd if=/dev/zero of=/zero.file bs=1M # 报错后,删除这个文件 sudo rm -f /zero.file # 刷新文件系统 sync方法 B:使用 zerofree(更彻底,但需要重启进单用户模式) 如果方法A效果不佳,可尝试此法。
- 重启虚拟机,在Grub菜单选择“恢复模式”(Recovery Mode)或按
e编辑启动项,将ro recovery nomodeset改为rw single init=/bin/bash。 - 卸载根分区(假设是 /dev/sda1):
umount /dev/sda1 - 执行:
zerofree -v /dev/sda1
- 重启虚拟机,在Grub菜单选择“恢复模式”(Recovery Mode)或按
第二步:在物理机(宿主机 Windows)上操作
这一步是将虚拟机里刚才标记的“全0”区域真正地从VHD文件中剔除。
注意: 必须先关闭虚拟机。
方法一:使用 Hyper-V 管理器(图形化界面,最安全)
- 打开物理机上的 Hyper-V 管理器。
- 在右侧操作栏点击 “编辑磁盘...”。
- 定位磁盘:浏览找到你的虚拟机在D盘对应的
.vhdx文件。 - 选择操作:选择 “压缩”。
- 解释:“压缩”操作会移除未使用的块。
- 注意:如果“压缩”是灰色的或者不可选,说明该VHD文件有快照,必须先删除快照。
- 完成:按照向导点击完成。系统会开始处理,这个过程需要读取整个VHD文件并写入一个新的、更小的文件。
空间预警:
- “压缩”过程需要临时的物理空间。Hyper-V通常会创建一个新的小文件,处理完后再替换旧文件。
- 如果 D盘剩余的 43.4 GB 小于虚拟机当前“实际已用数据量”(注意不是总大小,是删文件前的大小),操作可能会失败,提示空间不足。
方法二:使用 PowerShell(如果图形界面失败)
以管理员身份运行 Windows PowerShell:
# 语法:Optimize-VHD -Path "VHD文件路径" -Mode Full
Optimize-VHD -Path "D:\你的路径\你的虚拟机磁盘.vhdx" -Mode Full
如果D盘空间实在不够怎么办?
如果上述“压缩”步骤提示空间不足(因为43.4GB可能不足以支撑重写过程),你有两个变通方案:
方案 A:利用 C 盘空间(如果有)
- 将虚拟机的
.vhdx文件移动到 C 盘(C盘有69GB可用)。 - 在 Hyper-V 设置里重新指向 C 盘的磁盘文件。
- 在 C 盘执行上述的“压缩”操作。
- 压缩完成后,文件变小了,再移回 D 盘。
方案 B:导出再导入(最稳妥的瘦身法)
这种方法不需要额外的临时空间,但耗时较长。
- 在 Hyper-V 管理器中,右键点击该虚拟机 -> 导出。
- 选择一个有足够空间的路径(或者利用导出过程自动瘦身,但这取决于版本)。
- 更好的方式是:新建一个虚拟机,创建一个比当前小的新VHDX,然后将旧数据迁移过去(这种方法太繁琐,不推荐)。
总结建议
- 先在 Ubuntu 里运行
dd命令填零并删除。 - 关机。
- 尝试直接用 Hyper-V 的 “编辑磁盘” -> “压缩” 功能。
- 如果报错空间不足,先将
.vhdx文件剪切到 C 盘,在 C 盘压缩完变小后,再移回 D 盘。
明白了,虚拟机文件总量超过 3T,而物理机 D 盘剩余空间只有 43.4 GB。
这个情况非常关键。直接回答你:在 D 盘剩余空间不足的情况下,对 3T 的虚拟机进行“压缩/精简”操作极其危险,且通常无法完成。
原因如下: Hyper-V 的压缩(精简)机制通常需要创建一个“临时副本”或者移动数据块。对于 3T 的文件,即使只用了 100G,压缩过程往往也需要一定的“周转空间”来重新排列数据块。43GB 的剩余空间对于 3TB 级别的文件操作来说,就像是试图用一个小勺子去挖空一座山,空间完全不够周转,极大概率会导致操作失败,甚至损坏虚拟机文件。
但是,你还有一个机会,不需要物理机腾出空间,直接在虚拟机内部通过 PowerShell 命令进行“在线精简”。
请严格按照以下步骤操作,这是目前最安全、无需额外物理空间的方案:
核心方案:使用 PowerShell 进行在线优化(推荐)
这个方法利用了 Windows 10/Server 2016 及以上版本 Hyper-V 的新特性,可以直接通知虚拟硬盘回收未使用的块,而不需要创建巨大的临时文件。
1. 虚拟机内部操作 (Ubuntu)
你需要先让 Ubuntu 系统把“已删除文件”的状态告诉底层硬盘。
-
确保虚拟机内安装了
open-vm-tools或者hyperv-daemons(通常 Kylin/Ubuntu 自带或需安装):sudo apt-get install linux-virtual-lts-xenial(或者确保hv_utils模块已加载) 检查模块:lsmod | grep hv_utils如果有输出,说明驱动正常。 -
执行“discard”操作(关键步骤): 在 Ubuntu 终端中运行以下命令,手动触发 TRIM/Discard 指令:
sudo fstrim -v /如果还有挂载其他数据盘,也要对它们执行此命令,例如sudo fstrim -v /data注意: 如果命令成功执行,它会显示“XXX bytes were trimmed”。这一步仅仅是告诉 Hyper-V:“这些块我不用了”。
2. 物理机操作 (Windows 宿主机)
现在需要在宿主机上强制 Hyper-V 回收这些空间。
-
关闭虚拟机(必须关机,不能是保存状态)。
-
以管理员身份打开 Windows PowerShell(不是 CMD)。
-
执行以下命令(请替换为你的实际路径):
Optimize-VHD -Path "D:\你的虚拟机文件夹\你的虚拟硬盘文件.vhdx" -Mode Full注意:如果你的虚拟机文件是
.vhd格式,这个命令可能不支持,必须是.vhdx。如果是.vhd,你只能转为 vhdx 或者使用导出法。
备选方案:如果上述方法失败(空间实在不足)
如果 Optimize-VHD 报错提示空间不足,或者你的虚拟硬盘是固定大小(Fixed Size)而不是动态扩展(Dynamic),那么你面临一个尴尬的境地:物理机 D 盘必须腾出空间。
因为 3T 的文件,任何涉及“移动”或“复制”的操作(如导出虚拟机、编辑磁盘)都需要至少等同于“已用数据量”的临时空间。
如果必须压缩且上述方法无效,你只有两条路:
-
物理腾挪(最稳妥): 找一块移动硬盘,把 D 盘其他不重要的文件移走,务必腾出至少 50GB - 100GB 的空闲空间。 然后使用 Hyper-V 管理器:
- 右键虚拟机 -> 导出(导出到一个临时文件夹)。
- 导出完成后,删除原来的虚拟机和原来的 3T 文件。
- 将导出的虚拟机重新注册进来。 这是唯一能 100% 确保把 3T 文件瘦身的方法,但前提是你得有地方存放那个“导出”过程的临时文件。
-
拆分存储(如果有多余硬盘): 如果你的电脑有 E 盘或其他盘,可以将虚拟机的硬盘文件移动到那个盘,那个盘空间如果大,就在那个盘上进行压缩操作。
总结建议
- 先在 Ubuntu 里运行
sudo fstrim -v /。 - 关机。
- 在 Windows PowerShell (管理员) 里运行
Optimize-VHD -Path "D:路径xxx.vhdx" -Mode Full。 - 千万不要尝试使用“编辑磁盘 -> 压缩”向导,那个向导在空间不足时极容易报错卡死。
如果 Optimize-VHD 提示空间不足,那你只能去清理 D 盘其他文件了,否则神仙难救。