我有一台 VirtualBox VM,配置了非常大的硬盘(大于主机)。由于我的错误,VM 上的一个程序生成了大量日志文件,VDI 文件大小不断增长,直到主机上没有空间。
现在我删除了日志文件,但使用后 VDI 文件大小并没有变小VBoxManage.exe modifyhd "C:\Virts\mybox-i386.vdi" compact
有没有办法真正压缩 VDI 文件大小?谢谢!
答案1
您必须执行以下步骤:
在客户机中运行碎片整理程序(仅限 Windows)
使可用空间无效:
有Linux 客户端运行这个:
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 客户机, 下载删除从 Sysinternals 运行此命令:
sdelete.exe c: -z
(将 C: 替换为 VDI 的驱动器号)
关闭客户虚拟机
现在运行 VBoxManage 的
modifymedium
命令带有--compact
选项:有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
VBoxManage 位于此处:/Applications/VirtualBox.app/Contents/MacOS/VBoxManage
这会减小 vdi 的大小。
答案2
Windows 主机上的 Debian 客户机使用 discard/TRIM。
这本身并不是一个直接的答案,因为我是在解决问题,而不是问题。此解决方案不是定期压缩映像,而是使用丢弃来自动删除主机 VM 磁盘映像中未使用的块。
此解决方案需要支持连续 TRIM 的客户文件系统。Arch Linux wiki 有一个支持 TRIM 操作的文件系统列表。
FDE 和 cryptoroot 不包含在内,因为存在安全问题,而且这个问题的其他解决方案都不允许压缩。Arch Linux wiki 上有关于TRIM 和 dm-crypt 设备。
理论上,这将适用于使用 VDI 存储的 VBox 主机上的所有 Linux 客户机。
主机配置
discard
在 VBox 退出且没有虚拟机运行时,通过在虚拟机的配置文件中为每个磁盘设置和来为磁盘添加丢弃支持nonrotational
。此时discard
不在 GUI 中,但nonrotational
显示为“固态硬盘”复选框。(参考:vbox 论坛,丢弃支持)
<AttachedDevice discard="true" nonrotational="true" type="HardDisk" [..other options..] >
启动虚拟机,并验证 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
现在使用 手动修剪空闲块fstrim
。fstrim
使用已安装的文件系统,而不是支持它的块设备。无需在 中设置连续丢弃fstab
,可以每周 cron 执行此操作。(对于可能对 TRIM 的支持存在疑问的物理 SSD,建议每周 cron 执行,但这与此无关,因为底层 SSD 由主机操作系统处理。请参阅:SSD 修剪警告)。
fstrim /
fstrim /build
此时,VM 内部文件系统的大小和 VM 映像的大小应该非常接近。
已测试:
- Guest1:Debian 8.7,内核:来自反向移植的 linux 4.8 grsec,文件系统:ext4
- Guest2:Debian 9 RC2,内核:linux 4.9,文件系统:ext4
- 主机1:VBox 5.1.14,Win7,图像格式:VDI
- 主机2:VBox 5.1.14,Win8.1,图像格式:VDI
答案3
我在装有 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
我在评论中留下了链接,以便您可以(大致)了解它是如何工作的。
编辑
好吧,在经历了这一切之后,我尝试了CloneVDI 工具并且只需一次点击就能在更短的时间内完成出色的工作。
答案4
对旧版(~1997-2007)操作系统的重要说明
总的来说,前面给出的答案中的技术都是有效的;但是,有一个非常重要的特殊情况。
在一段时间内(大概是 1997-2007 年左右),32 位操作系统仍是主流,但 2GB 以上的硬盘已开始使用。因此,当尝试通过写入一个全零文件来占用所有可用空间时(这应始终以 root 身份执行,以包括 root 的特权可用空间,其他人无法触及),您可能会看到:
文件过大
而不是你所期望的:
设备上没有剩余空间。
如果发生这种情况,您很可能已经达到了 2GB 的文件大小限制。这在当时很常见,因为许多文件操作以有符号的 32 位整数返回结果,因此负值可能会报告错误代码。这实际上意味着,如果不采取特殊措施,偏移结果将被限制为 2^31 字节。
解决方法很简单:继续创建单独的、不同名称的零文件,直到磁盘实际空间不足。
如果您是一名想要在课堂上演示这种情况的讲师,那么包含旧版 Red Hat Linux 7.0 的 4GB 磁盘映像就足够了。