Skip to main content

压缩Hyper-V的虚拟硬盘(VHD/VHDX)释放空间

针对你的情况,核心问题在于Hyper-V的虚拟硬盘(VHD/VHDX)具有“只增不减”的特性。即使你在虚拟机(Ubuntu)内部删除了大量文件,物理机上的VHD文件依然保持着膨胀后的大小,不会自动释放空间。

目前的困境是:

  • 物理机(宿主机)D盘:剩余空间 43.4 GB。
  • 虚拟机(客户机)内部:已删除文件,显示有大量空闲空间。
  • 目标:对虚拟机文件进行压缩(精简),释放物理机D盘空间。

结论: 在D盘剩余43.4 GB的情况下,只要你的虚拟机VHD文件不是特别巨大(例如超过100GB),通常是可以进行压缩处理的

以下是具体的操作步骤,分为“零填充”和“压缩”两个阶段。


第一阶段:在虚拟机(Ubuntu)内部操作

这一步的目的是告诉硬盘:“这些块现在是空的,可以被回收”。

  1. 安装 zerofree 工具(推荐方式) 在Ubuntu终端中执行:

    sudo apt-get update
    sudo apt-get install zerofree
    
  2. 执行零填充 由于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效果不佳,可尝试此法。

    1. 重启虚拟机,在Grub菜单选择“恢复模式”(Recovery Mode)或按 e 编辑启动项,将 ro recovery nomodeset 改为 rw single init=/bin/bash
    2. 卸载根分区(假设是 /dev/sda1):umount /dev/sda1
    3. 执行:zerofree -v /dev/sda1

第二步:在物理机(宿主机 Windows)上操作

这一步是将虚拟机里刚才标记的“全0”区域真正地从VHD文件中剔除。

注意: 必须先关闭虚拟机。

方法一:使用 Hyper-V 管理器(图形化界面,最安全)

  1. 打开物理机上的 Hyper-V 管理器
  2. 在右侧操作栏点击 “编辑磁盘...”
  3. 定位磁盘:浏览找到你的虚拟机在D盘对应的 .vhdx 文件。
  4. 选择操作:选择 “压缩”
    • 解释:“压缩”操作会移除未使用的块。
    • 注意:如果“压缩”是灰色的或者不可选,说明该VHD文件有快照,必须先删除快照。
  5. 完成:按照向导点击完成。系统会开始处理,这个过程需要读取整个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 盘空间(如果有)

  1. 将虚拟机的 .vhdx 文件移动到 C 盘(C盘有69GB可用)。
  2. 在 Hyper-V 设置里重新指向 C 盘的磁盘文件。
  3. 在 C 盘执行上述的“压缩”操作。
  4. 压缩完成后,文件变小了,再移回 D 盘。

方案 B:导出再导入(最稳妥的瘦身法)

这种方法不需要额外的临时空间,但耗时较长。

  1. 在 Hyper-V 管理器中,右键点击该虚拟机 -> 导出
  2. 选择一个有足够空间的路径(或者利用导出过程自动瘦身,但这取决于版本)。
  3. 更好的方式是:新建一个虚拟机,创建一个比当前小的新VHDX,然后将旧数据迁移过去(这种方法太繁琐,不推荐)。

总结建议

  1. 先在 Ubuntu 里运行 dd 命令填零并删除。
  2. 关机
  3. 尝试直接用 Hyper-V 的 “编辑磁盘” -> “压缩” 功能。
  4. 如果报错空间不足,先将 .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 系统把“已删除文件”的状态告诉底层硬盘。

  1. 确保虚拟机内安装了 open-vm-tools 或者 hyperv-daemons(通常 Kylin/Ubuntu 自带或需安装): sudo apt-get install linux-virtual-lts-xenial (或者确保 hv_utils 模块已加载) 检查模块:lsmod | grep hv_utils 如果有输出,说明驱动正常。

  2. 执行“discard”操作(关键步骤): 在 Ubuntu 终端中运行以下命令,手动触发 TRIM/Discard 指令: sudo fstrim -v / 如果还有挂载其他数据盘,也要对它们执行此命令,例如 sudo fstrim -v /data

    注意: 如果命令成功执行,它会显示“XXX bytes were trimmed”。这一步仅仅是告诉 Hyper-V:“这些块我不用了”。

2. 物理机操作 (Windows 宿主机)

现在需要在宿主机上强制 Hyper-V 回收这些空间。

  1. 关闭虚拟机(必须关机,不能是保存状态)。

  2. 管理员身份打开 Windows PowerShell(不是 CMD)。

  3. 执行以下命令(请替换为你的实际路径):

    Optimize-VHD -Path "D:\你的虚拟机文件夹\你的虚拟硬盘文件.vhdx" -Mode Full
    

    注意:如果你的虚拟机文件是 .vhd 格式,这个命令可能不支持,必须是 .vhdx。如果是 .vhd,你只能转为 vhdx 或者使用导出法。

备选方案:如果上述方法失败(空间实在不足)

如果 Optimize-VHD 报错提示空间不足,或者你的虚拟硬盘是固定大小(Fixed Size)而不是动态扩展(Dynamic),那么你面临一个尴尬的境地:物理机 D 盘必须腾出空间。

因为 3T 的文件,任何涉及“移动”或“复制”的操作(如导出虚拟机、编辑磁盘)都需要至少等同于“已用数据量”的临时空间。

如果必须压缩且上述方法无效,你只有两条路:

  1. 物理腾挪(最稳妥): 找一块移动硬盘,把 D 盘其他不重要的文件移走,务必腾出至少 50GB - 100GB 的空闲空间。 然后使用 Hyper-V 管理器:

    • 右键虚拟机 -> 导出(导出到一个临时文件夹)。
    • 导出完成后,删除原来的虚拟机和原来的 3T 文件。
    • 将导出的虚拟机重新注册进来。 这是唯一能 100% 确保把 3T 文件瘦身的方法,但前提是你得有地方存放那个“导出”过程的临时文件。
  2. 拆分存储(如果有多余硬盘): 如果你的电脑有 E 盘或其他盘,可以将虚拟机的硬盘文件移动到那个盘,那个盘空间如果大,就在那个盘上进行压缩操作。

总结建议

  1. 先在 Ubuntu 里运行 sudo fstrim -v /
  2. 关机。
  3. 在 Windows PowerShell (管理员) 里运行 Optimize-VHD -Path "D:路径xxx.vhdx" -Mode Full
  4. 千万不要尝试使用“编辑磁盘 -> 压缩”向导,那个向导在空间不足时极容易报错卡死。

如果 Optimize-VHD 提示空间不足,那你只能去清理 D 盘其他文件了,否则神仙难救。