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


301

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

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

有没有一种方法可以真正压缩VDI文件的大小?谢谢!

Answers:


507

您必须执行以下步骤:

  1. 在来宾中运行碎片整理(仅Windows)
  2. 消除可用空间:

    使用Linux Guest运行以下命令:

    dd if=/dev/zero of=/var/tmp/bigemptyfile bs=4096k ; rm /var/tmp/bigemptyfile
    

    要么:

    telinit 1
    mount -o remount,ro /dev/sda1
    zerofree -v /dev/sda1
    

    使用Windows Guest,从Sysinternals 下载SDelete并运行以下命令:

    sdelete.exe c: -z
    

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

  3. 关闭访客虚拟机

  4. 现在,运行modifymedium带有以下--compact选项的VBoxManage的命令:

    使用Linux主机运行此命令:

    vboxmanage modifymedium --compact /path/to/thedisk.vdi
    

    使用Windows主机运行此命令:

    VBoxManage.exe modifymedium --compact c:\path\to\thedisk.vdi
    

    Mac主机上,运行以下命令:

    VBoxManage modifymedium --compact /path/to/thedisk.vdi
    

这样可以减小vdi大小。


14
对于下一个人,我的命令最终如下所示:“ C:\ Program Files \ Oracle \ VirtualBox \ VBoxManage.exe” Modifyhd“ C:\ Users \ daniel \ VirtualBox VMs ..... \ thedisk.vdi”-紧凑型
Daniel

36
根据zerofree Linux实用程序的联机帮助页(manpages.ubuntu.com/manpages/natty/man8/zerofree.8.html),对于这项工作,zerofree应该比dd更好。不建议使用dd,因为“它很慢”,“使磁盘映像(临时)增长到最大程度”,“(临时)使用了磁盘上的所有可用空间,因此其他并发写入操作可能会失败”。Zerofree可通过apt在Ubuntu Linux上使用,也可以自己编译。
Dakatine

27
有趣的是,zerofree的联机帮助页指出,dd并发写入将失败,但是zerofree需要将文件系统安装为只读!* duh *
Madarco 2014年

7
提示:dd ...; rm /bigfile将这两个命令放在一行上,如下所示:,这样可以最大程度地减少磁盘满时的时间,以防您不等待dd完成。
jlh 2014年

21
@Dakatine使用VirtualBox 4.3.10,磁盘映像文件没有达到最大程度。VirtualBox足够聪明,不必费心将所有零块写入物理磁盘。
jlh 2014年

12

我在装有Windows guest虚拟机的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

我在评论中留下了链接,因此您可以(一定程度上)知道它是如何工作的。

编辑

好吧,毕竟,我尝试了CloneVDI工具,它用更少的时间和一次点击就完成了出色的工作。


5
您可能会认为在此类站点上会针对DOS突出显示某种语法,但没有。它看起来在记事本++更漂亮
CAD家伙

1
@CAD_bloke需要解析引擎,并且当您考虑在SE上发布不同语言的数量时,您正在查看的是一个巨大的项目。试想有多少版本和DOS的方言有例如,这就是之前你甚至到Linux等
Caltor

很好的一点。具有讽刺意味的强调在栈上交换iOS应用。
CAD猛击

2
是的,CloneVDI是更好,更快的个人使用方式
VarunAgw 2015年

6

Windows主机上的Debian guest使用drop / TRIM。

这本身不是直接的答案,因为我要解决的是问题,而不是问题。该解决方案没有定期压缩映像,而是使用丢弃来自动删除主机的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..] >

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

sudo hdparm -I /dev/sda | grep TRIM

访客配置

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

devices {
...
    issue_discards = 1
}

在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

重新挂载文件系统,使它们选择新的选项。

sudo mount -o remount /
sudo mount -o remount /build

使用手动修剪自由块fstrimfstrim使用已安装的文件系统,而不是支持它的块设备。fstab可以在每周cron中完成此操作,而不必在中设置连续丢弃。(建议对可能对TRIM的支持有问题的物理SSD每周进行cron计划,但这在这里不重要,因为底层SSD由主机OS处理。请参阅:ssd trim warning)。

fstrim /
fstrim /build

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

经过测试:

  • 来宾1:Debian 8.7,内核:来自反向端口的linux 4.8 grsec,文件系统:ext4
  • Guest2:Debian 9 RC2,内核:linux 4.9,文件系统:ext4
  • 主机1:VBox 5.1.14,Win7,图像格式:VDI
  • Host2:VBox 5.1.14,Win8.1,图像FMT:VDI

2

对于MacOS Guest,请执行以下操作:

  1. 消除来宾系统中的可用空间:

    diskutil secureErase freespace 0 "/Volumes/Macintosh HD"
    

    (用驱动器名称替换/ Volumes / Macintosh HD)

  2. 关闭访客虚拟机

  3. 运行此命令以减小VDI磁盘映像大小

    VBoxManage modifyhd /path/to/thedisk.vdi --compact
    

    要么

    VBoxManage modifymedium /path/to/thedisk.vdi --compact
    

1

我将其用于安装在Windows VirtualBox中的虚拟Debian上的VDI映像。这不是一个通用的解决方案,但至少应该让您了解我的工作重点。

Debian中的命令:

root@debian:~# lsblk  # show partitions
名称:最低RM尺寸RO型MOUNTPOINT 
sdb 8:16 0 128G 0磁盘 
└─sdb18:17 0 128G 0 part / mnt / web#这是利益的分区!
sda 8:0 0 64G 0磁盘 
├─sda18:1 0 61,4G 0部分/ 
├─sda28:2 0 1K 0部分 
s─sda58:5 0 2,7G 0部分 
[SWAP] sr0 11:0 1 56,3M 0 rom
root@debian:~# service mysql stop  # terminate all operations with partition
root@debian:~# service apache2 stop  # terminate all operations with partition
root@debian:~# umount /mnt/web  # unplug partition
root@debian:~# apt-get install zerofree  # install tool for filling in zeros to empty space
root@debian:~# zerofree -v /dev/sdb1  # fill with zeros
root@debian:~# poweroff  # shut down machine

Windows中的命令:

C:\Program Files\Oracle\VirtualBox>VBoxManage.exe modifyhd --compact "D:\VirtualBox VMs\web.vdi"  # convert zeros to empty space

希望能帮助到你 :)


1

我不想在OS中启用TRIM支持,因为每次删除数据都会强制将VDI文件中的数据压缩,从而使VDI文件位于经典旋转磁盘上时,来宾系统无法使用。对我来说,更好的方法是手工压实,例如每月一次。

在常规压缩期间,VDI文件内容将复制到新文件。这需要主机光盘上有一些(有时很大)可用空间。

我的解决方案与Andrew Domaszek所指出的类似。即使使用NTFS(Windows10),它也能很好地工作。

去做这个:

  • 创建一个可以使用GParted Live CD引导的新虚拟机(您可以使用喜爱的Linux发行版)。
  • 编辑机器设置并设置SATA磁盘控制器
  • 添加要压缩的现有VDI文件
  • 将基于VDI的光盘更改为具有TRIM支持的SSD可见:

    VBoxManage storageattach "gpared live" --storagectl "SATA" --port 0 --discard on --nonrotational on
    VBoxManage storageattach "gpared live" --storagectl "SATA" --port 1 --discard on --nonrotational on
    
  • 启动机器

  • 在Linux根shell中,挂载NTFS分区 mount /dev/sda2 /mnt
  • 零可用空间 dd if=/dev/zero of=/mnt/bigfile
  • rm /mnt/bigfile
  • 在不创建新文件的情况下强制压缩VDI: fstrim -v /mnt

0

补充公认的答案的一个非常巧妙的技巧是,通过使用主机上的压缩文件系统(例如,选择压缩虚拟机上NTFS属性上的虚拟驱动器的文件夹),在将来宾空间归零后完全不进行任何压缩。 Windows主机)。实际上,这样做的好处是可以节省更多空间,因为操作系统倾向于保留大量重复的文本或二进制文件(例如,将15GB的空间清零的30GB来宾驱动器可以在主机驱动器上变为4GB)。

需要注意的是,实际硬件上的驱动器访问可能会增加,并且CPU使用率会略有增加。


0

旧版(〜1997-2007)操作系统的重要说明

通常,先前给出的答案中的技术是有效的。但是,有一个非常重要的特殊情况。

在一段时间(也许是1997-2007年左右)的一段时间内,仍然是32位操作系统,但是已经使用了大于2GB的硬盘。结果,当尝试通过写入零文件来消耗所有可用空间时(应始终以root身份进行操作,以包括root的特权可用空间,其他人都无法接触),您可能会看到:

文件过大

而不是您的期望:

设备上没有剩余空间。

如果发生这种情况,您很可能达到了2GB的文件大小限制。这在当时很常见,因为许多文件操作返回的结果都是带符号的32位整数,因此负值可以报告错误代码。这实际上意味着无需特殊措施即可将偏移结果限制为2 ^ 31字节。

解决方法很简单:继续创建单独的,名称不同的清零文件,直到磁盘实际空间不足为止。

如果您希望在课堂上演示这种情况,那么使用带Red Hat Linux 7.0旧副本的4GB磁盘映像就足够了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.