如何压缩 VirtualBox 的 VDI 文件大小?

Dee*_*Two 344 virtualbox vdi

我有一个 VirtualBox VM,它配置了一个非常大的硬盘大小(比主机大)。由于我的错误,VM 上的程序生成了大量日志文件,并且 VDI 文件大小不断增长,直到主机上没有空间为止。

现在我已经删除了日志文件,但使用后 VDI 文件大小并没有变小 VBoxManage.exe modifyhd "C:\Virts\mybox-i386.vdi" compact

有没有办法真正压缩 VDI 文件大小?谢谢!

mag*_*981 584

您必须执行以下步骤:

  1. 在来宾中运行碎片整理(仅限 Windows)

  2. 取消可用空间:

    使用Linux 来宾运行:

     dd if=/dev/zero of=/var/tmp/bigemptyfile bs=4096k ; rm /var/tmp/bigemptyfile
    
    Run Code Online (Sandbox Code Playgroud)

    或者:

     telinit 1
     mount -o remount,ro /dev/sda1
     zerofree -v /dev/sda1
    
    Run Code Online (Sandbox Code Playgroud)

    使用Windows 来宾,从 Sysinternals下载SDelete并运行:

     sdelete.exe c: -z
    
    Run Code Online (Sandbox Code Playgroud)

(将 C: 替换为 VDI 的驱动器号)

  1. 关闭来宾 VM

  2. 现在modifymedium使用以下--compact选项运行 VBoxManage 的命令:

    使用Linux 主机运行:

     vboxmanage modifymedium --compact /path/to/thedisk.vdi
    
    Run Code Online (Sandbox Code Playgroud)

    使用Windows 主机运行:

     VBoxManage.exe modifymedium --compact c:\path\to\thedisk.vdi
    
    Run Code Online (Sandbox Code Playgroud)

    使用Mac 主机运行:

     VBoxManage modifymedium --compact /path/to/thedisk.vdi
    
    Run Code Online (Sandbox Code Playgroud)

    VBoxManage 位于:/Applications/VirtualBox.app/Contents/MacOS/VBoxManage

这会减小 vdi 大小。

  • 根据 zerofree Linux 实用程序手册页 (http://manpages.ubuntu.com/manpages/natty/man8/zerofree.8.html),对于这项工作,zerofree 应该比 *dd* 更好。*dd* 不会被推荐,因为“它很慢”,“它使磁盘映像(临时)增长到最大范围”,“它(临时)使用磁盘上的所有可用空间,因此其他并发写入操作可能会失败”。Zerofree 可通过 *apt* 在 Ubuntu Linux 上获得,或者您可以自己编译它。 (40认同)
  • 有趣的是 *zerofree* 的联机帮助页指出 *dd* 其他并发写入将失败,但 zerofree 需要将文件系统挂载为只读!\*废话\* (34认同)
  • @Dakatine 使用 VirtualBox 4.3.10,磁盘映像文件_没有增长_到其最大程度。VirtualBox 足够聪明,不会费心将所有零块写入物理磁盘。 (24认同)
  • 对于下一个人,我的命令最终看起来像这样:"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyhd "C:\Users\daniel\VirtualBox VMs\....\thedisk.vdi" - -袖珍的 (21认同)
  • 提示:将两个命令放在一行上,如下所示:`dd ...; rm /bigfile`,这将最大限度地减少磁盘已满的时间,以防您不等待 `dd` 完成。 (8认同)
  • @Vincent 这就是这个程序的重点。您正在向新文件写入零,直到它填满整个可用空间,然后删除该文件。 (7认同)
  • @FrozenFlame /bigemptyfile 只是 magicandre1981 用于临时文件的任意名称,您可以随意命名。`sudo dd if=/dev/zero of=/zero.fill bs=4096k` 在功能上完全相同,它只会写入一个名为 `zero.fill` 的文件(你需要更改 `rm`命令删除此文件而不是`/bigemptyfile`) (3认同)
  • 作为参考,我必须删除我的快照才能有所作为。 (3认同)
  • 出现这个错误是正常的吗?dd:写入“/bigemptyfile”时出错:设备上没有剩余空间 (2认同)
  • `sdelete` 需要一个目标作为参数。示例 `sdelete.exe c: -z` (2认同)
  • @Andrea Lazzarotto 实际上 VBoxManage 和 vboxmanage 都存在于我安装了 VirtualBox 5.0.24 的 Linux 机器上。 (2认同)
  • @Victor,当我留下我之前的评论(我们谈论的是一年多前)时,我的 Ubuntu 系统上没有小写版本。只有大写字母出现。 (2认同)
  • 值得注意的是,Windows 10 客户机不会对标记为 SSD 的磁盘进行碎片整理。其余的对我有用。谢谢。 (2认同)
  • 老实说,我不知道为什么这是被接受的答案。如果我有 500GB VDI,在 win guest 中只使用了大约 100GB。 VDI大约是150GB。 sdelete 实际上会将 VDI 扩大到 500GB。而压缩后仅缩小了约480GB。所以它实际上使VDI变得更大。只需克隆 150GB VDI 并在其上运行紧凑型即可缩小至 120GB。我真的想对那个根本没有在最近的 NTFS 上测试这个的人竖起中指。浪费大量时间和精力。这仅适用于 Linux 来宾! (2认同)

CAD*_*oke 14

我在带有 Windows 来宾的 Windows 7 主机上,这是我写的一个批处理文件,用于压缩文件夹树中的所有 VDI

echo off
mode con:cols=140 lines=200
cls
:: see https://forums.virtualbox.org/viewtopic.php?p=29272#p29272
:: How can I reduce the size of a dynamic VDI on disk?
:: but that page says to use sdelete -s which is suboptimal. 
:: use -z as per http://technet.microsoft.com/en-us/sysinternals/bb897443.aspx

:: First run the sdelete -z c: inside the VMs that zero-out all the free space
:: THEN run this batch file 

Title Compacting Free space on Virtual Machine VMs

:: http://ss64.com/nt/for_r.html
:: http://stackoverflow.com/questions/8836368/windows-batch-file-how-to-loop-through-files-in-a-directory/8836401#8836401

Setlocal EnableDelayedExpansion
:: http://ss64.com/nt/delayedexpansion.html ... 
:: Notice that within the for loop we use !variable! instead of %variable%.

For /R %CD% %%G IN (*.vdi) DO (
 set ohai=%%G
 set lastfive=!ohai:~-5!
:: Skip snapshots which are named {guid}.vdi
 if NOT !lastfive!==}.vdi (
 echo .
 echo Compacting %%G
 "C:\Program Files\Oracle\VirtualBox\VboxManage.exe" modifyhd "%%G" --compact )
 )
 
pause 
exit
Run Code Online (Sandbox Code Playgroud)

我在评论中留下了链接,所以你可以(有点)告诉它是如何工作的。

编辑

好吧,毕竟,我尝试了CloneVDI 工具,它用更少的时间和一键完成了很好的工作。

  • 你会认为在这种网站上会有某种针对 DOS 的语法高亮显示,但没有。在 Notepad++ 中看起来更漂亮 (5认同)
  • @CAD_bloke 需要一个解析引擎,当您考虑在 SE 上发布的不同语言的数量时,您正在查看一个巨大的项目。试想一下,例如,有多少 DOS 版本和方言,那是在你甚至还没有进入 Linux 等之前。 (2认同)
  • 是的 CloneVDI 是个人使用更好更快的方式 (2认同)

小智 12

使用丢弃/修剪的 Windows 主机上的 Debian 来宾。

这本身并不是一个直接的答案,因为我正在解决问题,而不是问题。该解决方案不是定期压缩映像,而是使用丢弃来自动删除主机 VM 磁盘映像中未使用的块。

此解决方案需要一个支持连续 TRIM 的来宾文件系统。Arch Linux wiki 有一个支持 TRIM 操作的文件系统列表

FDE 和cryptoroot 没有特别涵盖,因为存在安全问题,而且这个问题的其他解决方案都不允许压缩。Arch Linux wiki 有关于TRIM 和 dm-crypt 设备的信息

理论上,这适用于使用 VDI 存储的 VBox 主机上的所有 Linux 来宾。

主机配置

在 VBox 退出且没有 VM 运行的情况下,通过在 VM 的配置文件中为每个磁盘设置discardnonrotational为每个磁盘添加丢弃支持。此时discard不在 GUI 中,而是显示nonrotational为“固态驱动器”复选框。(参考:vbox 论坛,放弃支持

<AttachedDevice discard="true" nonrotational="true" type="HardDisk" [..other options..] >
Run Code Online (Sandbox Code Playgroud)

启动 VM,并验证是否启用了 TRIM 支持:

sudo hdparm -I /dev/sda | grep TRIM
Run Code Online (Sandbox Code Playgroud)

访客配置

如果正在使用 LVM,请更改 中的丢弃设置/etc/lvm/lvm.conf。(参考:debian wiki,lvm.conf 示例

devices {
...
    issue_discards = 1
}
Run Code Online (Sandbox Code Playgroud)

在 fstab 中,将discard选项添加到您希望自动丢弃的文件系统(参考:debian wiki,fstab 示例

UUID=8db6787f-1e82-42d8-b39f-8b7491a0523c   /   ext4    discard,errors=remount-ro   0   1
UUID=70bfca92-8454-4777-9d87-a7face32b7e7   /build  ext4    discard,errors=remount-ro,noatime   0   1
Run Code Online (Sandbox Code Playgroud)

重新挂载文件系统,让他们选择新的选项。

sudo mount -o remount /
sudo mount -o remount /build
Run Code Online (Sandbox Code Playgroud)

现在手动修剪空闲块fstrimfstrim使用挂载的文件系统,而不是支持它的块设备。fstab这可以在每周的 cron 中完成,而不是在 中设置连续丢弃。(建议每周 cron 用于可能对 TRIM 支持有问题的物理 SSD,但这在此处无关紧要,因为底层 SSD 由主机操作系统处理。请参阅:ssd trim warning)。

fstrim /
fstrim /build
Run Code Online (Sandbox Code Playgroud)

此时,VM 内文件系统的大小和 VM 映像的大小应该非常接近。

测试:

  • Guest1:Debian 8.7,内核:来自 backports 的 linux 4.8 grsec,文件系统:ext4
  • Guest2:Debian 9 RC2,内核:linux 4.9,文件系统:ext4
  • Host1: VBox 5.1.14, Win7, image fmt: VDI
  • Host2:VBox 5.1.14,Win8.1,图像文件:VDI