本文地址:https://www.ebpf.top/post/shrink_vbox_vmdk_size

在使用 VirtualBox( VMDK 模式)管理虚拟机的时候,我们经常会遇到一些编译安装场景(比如编译 Linux 内核),会导致磁盘空间急剧膨胀,但是在编译完成后即使我们删除了相关的文件,在 VM 虚拟机占用主机的空间却并没有减少,这时候为了腾出磁盘空间或者更方便与他人分享,我们需要给 VM 的磁盘进行瘦身操作。

1.1 虚拟磁盘格式介绍

VirtualBox 主要支持下列虚拟磁盘格式为 VMDK 和 VDI:

  • VMDK(Virtual Machine Disk) 最初是由 VMware 为其产品研发的格式。该格式技术设计文档最初是闭源的,而现在已经开源,在 VirtualBox 里完全可用。这种格式有个功能是:把一个虚拟机的镜像分割成多个 2GB 大小的文件。如果你要把虚拟机镜像放在不支持大文件的文件系统(例如 FAT32)上,那么这个功能就非常有用。在其他的虚拟磁盘格式里,能做到同样功能的只有 Parallels 的 HDD。
  • VDI(Virtual Disk Image) 格式是 VirtualBox 新建虚拟机时默认选用的格式。也是 VirtualBox 的自有开放格式。

VirtualBox 支持的虚拟磁盘格式还有 VHDXHDD 等多种格式,详细信息请参考 VirtualBox 简体中文

1.2 用零字节填充空闲空间

VirtualBox 只有在空间被设置为零的情况下才知道这是磁盘中真正的空闲空间,这与我们在一般机器上通过标准的 rm 命令删除即可释放空间有很大不同。

为了实现这个效果,我们需要登录到 VM 主机中登录到虚拟机中,使用零字节空间填充掉空闲空间,然后再把填充的文件进行删除,即可达到效果。

$ cat /dev/zero > zero.fill; sync; sleep 1; sync; rm -f zero.fill
cat: write error: No space left on device

在命令执行完成后,会出先一个 “cat: write error: No space left on device” 的错误,这个错误恰恰表明我们使用零字节填充了所有的空闲空间。

至此,我们已经在 VM 虚拟机中成功地将空闲的空间进行了零字节填充,是时候进行真正的 “ 减肥 ” 操作了。

1.3 定位 VM 虚拟磁盘文件

在 VirtualBox 运行的主界面上,我们可以通过在虚拟机上点击右键,在弹出的菜单上选择 “Setting“ 选项,会弹出本虚拟相关的设置,切换到 ”Storage“ 选项卡。

图 1-1 进入 VM 的设置页面

在 ”Storage“ 选项卡的主界面中我们可以看到 VM 挂载的虚拟磁盘,点击虚拟磁盘选项,在右侧的 ”Attributes“ 信息栏中就可以在 ”Location“ 项中查询到选择虚拟磁盘所在的目录和文件名。

目录默认保存位置为 ~/VirtualBox VMs/ 目录下以 VM 名称命名的子目录下,如本例中的 ~/VirtualBox VMs/ubuntu_21_04_default_1632463892989_42055,其中 ubuntu_21_04_default_1632463892989_42055 为 VM 主机名。

图 1-2 进入 VM 的设置页面中的存储项详情

确定 VM 的虚拟磁盘所在目录后,我们通过终端进入到对应的目录,进行查看:

$ cd ~/VirtualBox\ VMs/ubuntu_21_04_default_1632463892989_42055/
$ ls -lh
-rw------- 1 dwh0403 staff 35G Sep 28 13:37 ubuntu-hirsute-21.04-cloudimg.vmdk
...

这里我们可以看到该该虚拟磁盘占用了 35G 的磁盘大小。我们可以通过 vboxmanage showhdinfo 命令查看 vmdk 文件的详情(如果后续需要继续使用 vmdk 格式需要):

$ vboxmanage showhdinfo ubuntu-hirsute-21.04-cloudimg.vmdk
UUID: 6a00f1e1-a53f-4a48-9f41-4f2a96248286
Parent UUID: base
State: created
Type: normal (base)
Location: /Users/dwh0403/VirtualBox VMs/ubuntu_21_04_default_1632463892989_42055/ubuntu-hirsute-21.04-cloudimg.vmdk
Storage format: VMDK
Format variant: dynamic default
Capacity: 40960 MBytes
Size on disk: 35717 MBytes
Encryption: disabled

为了压缩虚拟磁盘的空间,我们需要将 vmdk 格式转换成 vdi 格式。如果本机安装了 Vmware 产品,可以直接使用其提供的工具直接进行瘦身,参见 Vmware 磁盘管理样例

$ vboxmanage clonehd --format vdi ubuntu-hirsute-21.04-cloudimg.vmdk  ubuntu-hirsute-21.04-cloudimg.vdi
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone medium created in format 'vdi'. UUID: 46de9fce-0055-472b-aee2-128509e3685 $ ls -hl
-rw------- 1 dwh0403 staff 11G Sep 28 13:41 ubuntu-hirsute-21.04-cloudimg.vdi
... $ vboxmanage modifyhd ubuntu-hirsute-21.04-cloudimg.vdi --compact
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

待转换完成后,我们可以在当前目录进行查看可以发现 vdi 的文件大小已经降低至 11G(原始 vmdk 文件为 35G 大小),表明在转换过程中已经完成了磁盘空间的缩容。

1.4 将 VDI 格式的磁盘挂载(方案一,验证,推荐)

在转换 vdi 格式后,已经完成了空间的调整,如果我们并去强烈使用 vmdk 格式,我们可以直接将原来的 vmdk 格式虚拟磁盘从 VM 中卸载,然后将 vdi 格式的磁盘挂载即可。同时记得删除 vmdk 格式的虚拟磁盘。

在保持 VM 虚拟机关闭的情况下,进入到 VM 的存储设置页面,步骤与图 1-2 一致。

首先,在移除老的 vmdk 格式的虚拟磁盘上点击右键,在右键菜单属性中选择 ”Remove Attachment“:

然后鼠标选择磁盘控制器,选择添加磁盘按钮:

在弹出的添加磁盘文件的窗口中选择 ”Add“ 按钮,进入到选择文件窗口,选择我们新的 vdi 格式文件即可。

然后将 VM 虚拟机启动验证,如果一切顺利则完成了整个瘦身过程。

这里推荐使用 vdi 格式的虚拟磁盘格式,后续在磁盘空间吃紧的情况还可以使用下述命令调整大小:

$ VBoxManage modifyhd xxx.vdi --resize the_new_size

1.5 使用 VMDK 格式的磁盘挂载(方案二,未验证)

如果由于特殊原因必须使用 vmdk 格式的虚拟磁盘,我们需要将瘦身后的 vdi 格式文件重新转换为 vmdk 格式:

$ VBoxManage clonehd ubuntu-hirsute-21.04-cloudimg.vdi ubuntu-hirsute-21.04-cloudimg_new.vmdk --format vmdk

这里可以选择如上述方案相同的方式,通过去除虚拟磁盘再添加新的磁盘,如果使用原有的文件名字覆盖的话,由于转换过程中生成了新的 UUID,则会导致 VirtualBox 不能够识别新的虚拟磁盘,这里需要重新设置 UUID。

 $ vboxmanage internalcommands sethduuid ./ubuntu-hirsute-21.04-cloudimg <原 UUID 在此>

1.5.1 错误解决:

$ VBoxManage clonehd ubuntu_21_04_default_1632463892989_42055/ubuntu-hirsute-21.04-cloudimg.vdi  ubuntu-hirsute-21.04-cloudimg.vmdk --format vmdk
VBoxManage: error: UUID {6438d068-ae7b-467d-ab30-6e1228c30bd9} of the medium '/Users/dwh0403/VirtualBox VMs/ubuntu_21_04_default_1632463892989_42055/ubuntu-hirsute-21.04-cloudimg.vdi' does not match the value {46de9fce-0055-472b-aee2-128509e3685d} stored in the media registry ('/Users/dwh0403/Library/VirtualBox/VirtualBox.xml')
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component MediumWrap, interface IMedium, callee nsISupports
VBoxManage: error: Context: "CloneTo(pDstMedium, ComSafeArrayAsInParam(l_variants), NULL, pProgress.asOutParam())" at line 1068 of file VBoxManageDisk.cpp

如果有上述报错,建议修改 vmdk 生成的文件名重试。

1.6 总结

最后,我们可以已经成功完成了 VM 虚拟空间的瘦身,这对于我们在某些场景下进行功能测试还是非常有帮助。

1.7 参考

VirtualBox VM 空间瘦身记(vmdk)的更多相关文章

  1. APK瘦身记,如何实现高达53%的压缩效果

    作者:非戈@阿里移动安全 1.我是怎么思考这件事情的 APK是Android系统安装包的文件格式,关于这个话题其实是一个老生常谈的题目,不论是公司内部,还是外部网络,前人前辈已经总结出很多方法和规律. ...

  2. APK瘦身记,怎样实现高达53%的压缩效果

    作者:非戈@阿里移动安全,很多其它技术干货.请訪问阿里聚安全博客 1.我是怎么思考这件事情的 APK是Android系统安装包的文件格式.关于这个话题事实上是一个老生常谈的题目.不论是公司内部.还是外 ...

  3. VirtualBox虚拟机磁盘瘦身

    操作系统 : windows7_x64 VirtualBox 版本 : 4.3.28 原理: 使用0填充虚拟系统磁盘,然后删除填充文件,再使用VBoxManage进行压缩. Linux系统磁盘瘦身 一 ...

  4. .NET跨平台实践:Linux .Net Core自宿主应用程序瘦身记

    一,.NET Core 自宿主应用程序个头很大 发布.NET Core应用程序有两个方式,一种是“便携式”,一种是“自宿主式”.便携式发布时,目标程序不带.net core运行环境,所以“个头”很小, ...

  5. 虚拟机硬盘vmdk压缩瘦身并挂载到VirtualBox

    这个问题其实困扰了挺久的,一直没闲情去解决,网上搜索过很多压缩方法感觉都太麻烦太复杂,因最近在windows上搞docker就一并解决了. 压缩vmdk 首先下载DiskGenius,这工具很牛X,相 ...

  6. iOS安装包瘦身的那些事儿

    在我们提交安装包到App Store的时候,如果安装包过大,有可能会收到类似如下内容的一封邮件: 收到这封邮件的时候,意味着安装包在App Store上下载的时候,有的设备下载的安装包大小会超过100 ...

  7. iOS可执行文件瘦身方法

    缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...

  8. 【转】iOS可执行文件瘦身方法

    http://blog.cnbang.net/tech/2544/ 缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我 ...

  9. 为Windows 7的winsxs目录瘦身,谨慎。

    刚使用Win7 系统不久,前段时间在清理系统垃圾时发现,win7系统的windows文件夹下的winsxs 文件夹占用空间很大,想清理之,却提示无权限无法清理.随即在网上查了个到底,原来winsxs是 ...

随机推荐

  1. C#多线程详解(一) Thread.Join()的详解

    bicabo   C#多线程详解(一) Thread.Join()的详解 什么是进程?当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程 ...

  2. WPF 中的 Command 命令

    <Window x:Class="CommandDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx ...

  3. TortoiseGit冲突和解决冲突

    产生冲突原因 产生:多个开发者同时使用或者操作git中的同一个文件,最后在依次提交commit和推送push的时候,第一个操作的是可以正常提交的,而之后的开发者想要执行pull(拉)和pull(推)操 ...

  4. rollup 使用babel7版本的插件rollup-plugin-babel,rollup-plugin-babel使用报错解决办法。

    最近在研究rollup,想吐槽下rollup的官方文档写的真的太简单了,而且照着文档一步步来还报错,说明文档年代有点久远啊... 照着文档使用rollup-plugin-babel报错,首先打开rol ...

  5. 眼见为实,看看MySQL中的隐藏列!

    在介绍mysql的多版本并发控制mvcc的过程中,我们提到过mysql中存在一些隐藏列,例如行标识.事务ID.回滚指针等,不知道大家是否和我一样好奇过,要怎样才能实际地看到这些隐藏列的值呢? 本文我们 ...

  6. 5M1E,软件质量管理最佳解决方案

    - 如何做好一个产品? - 用户.需求.文化.价值.设计.流程,这些因素缺一不可.- 那么,如何做好产品的质量管理?- 人.机器.物料.方法.环境.测量,这些因素同样缺一不可.能够影响产品质量波动的因 ...

  7. SpringBoot笔记(1)

    一.Spring能做什么 微服务 响应式开发 分布式云开发 web开发 无服务开发(云) 批处理业务等 二.SpringBoot作用 能快速创建出生产级别的Spring应用 SpringBoot是整合 ...

  8. TCP连接中的状态

    1. 正常状态转换 我们用图 3-13 来显示在正常的 TCP 连接的建立与终止过程中,客户与服务器所经历的不同状态.读者可以对照图 3-12 来阅读,使用图 3-12 的状态图来跟踪图 3-13 的 ...

  9. Pulsar の 保证消息的顺序性、幂等性和可靠性

    原文链接:Pulsar の 保证消息的顺序性.幂等性和可靠性 一.背景 前面两篇文章,已经介绍了关于Pulsar消费者的详细使用和自研的Pulsar组件. 接下来,将简单分析如何保证消息的顺序性.幂等 ...

  10. HCNP Routing&Switching之动态路由协议IS-IS基础

    前文我们了解了OSPF的特殊区域相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15236330.html:今天我们来聊一聊另一动态路由协议IS-IS相 ...