解决VMware虚拟机磁盘压缩空间问题

发布于 2023-02-01  740 次阅读


虚拟机里清理删除了大文件,但是压缩却挤不出空间。

最近在回收空间,发现电脑里的VMware虚拟机文件是一个大头。虚拟机里最占地方的就是虚拟磁盘。虚拟机里清理删除了一些以前项目的大文件,但是压缩挤不出空间。

虚拟磁盘格式是多文件、不预分配。因此电脑(宿主机)里虚拟磁盘文件看起来是这样:

虚拟磁盘

后缀名全都是vmdk,许多文件名含有”sxxx“,而且很大;第一个文件大小仅几K,可以当成文本打开。第一个vmdk包含了整个磁盘的信息,其中就有Extent description ,包含了文件的顺序信息。

# Extent description
RW 8323072 SPARSE "Windows 10 x64-s001.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s002.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s003.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s004.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s005.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s006.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s007.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s008.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s009.vmdk"
RW 8323072 SPARSE "Windows 10 x64-s010.vmdk"
RW 655360 SPARSE "Windows 10 x64-s011.vmdk"

因此多文件的虚拟磁盘结构就像链表一样,分块后插入信息时索引比较方便。而且和物理磁盘一样,文件存放不是连续的。

想要回收虚拟磁盘空间,VMware在虚拟机设置中自带了 磁盘实用工具 ,包括了

  • 映射:将该虚拟机磁盘映射到本地卷
  • 碎片整理:整理文件碎片并整合可用空间
  • 扩展:扩展磁盘容量
  • 压缩:压缩磁盘以回收未使用的空间

这里主要说第四个。

先腾出来一些地方。如果是一台windows虚拟机,清理磁盘文件可以选择映射为本地磁盘,以熟悉的方式删除文件。但是映射linux的磁盘到本地,windows explorer是无法识别的。只能在虚拟机内部清理文件。

遇到的问题是,我已经在虚拟机里清理删除了一些以前项目的大文件,腾出了很大地方,但是压缩并不能把空间让出来。

显著的现象就是虚拟机内部统计的容量占用和VMware显示的磁盘容量(体积)相差较大。即使利用压缩功能很多次,最终还是在一个值压不动了。(这里是一台Ubuntu的虚拟机的磁盘)

可以确定不是虚拟机统计的问题。有一个专用的50G虚拟磁盘用来放大文件,里面有3个G的项目文件,删除了里面所有的文件之后尝试压缩,还是好几个G,压不动了。想象中正确的结果是这个虚拟磁盘的体积应该只剩下很小。

看到网上的办法,利用linux自带的zero文件,把空间占满再删除,再用vmware-tool 压缩空间。

结果并不奏效。

摸索中突然想起来以前用DiskGenius时注意到,它可以打开虚拟磁盘。尝试把vmdk拖进去,打开了。甚至支持查看linux的ext4文件系统!!以后可以不用打开虚拟机找文件了。

DiskGenius打开ubuntu的虚拟磁盘

DG上显示的已用百分比也能证明Ubuntu的统计没错。

受此网上填0办法的启发,利用DiskGenius清除分区空闲空间。(填充要选0,填F的话会把空间占满)

清除分区空闲空间

然后再用VMware的压缩。实际用量就和虚拟磁盘文件符合了。

至此,成功。


事后思考为什么:

我们看到的已用空间,并不是真正的”已用空间“。一块全新的硬盘就是一片“处女地”,对于硬盘只要这里记录文件的介质(磁道、电子)发生改变,就算”已用“,文件删除并不会把这里的介质复位。这就是为什么删除单个文件不管有多大都是用一样的时间。可以参考这个链接:为什么 Steam 删除 80G 的游戏只用了一秒? 文件删除只是不计入统计,曾经占用的位置可以被覆盖利用。系统知道标记可以写入,就计入未用空间,但是硬盘这里并没有复原为空地。因此VMware磁盘工具会把这里统计为已用空间。就不会被压缩掉。想要释放这片地,必须手动复原为”处女地“(全部填0),就会被视为”处女地“压缩释放掉(前提是虚拟磁盘格式是”不预分配“)。