Answers:
您必须执行以下步骤:
消除可用空间:
使用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的驱动器号)
关闭访客虚拟机
现在,运行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大小。
dd ...; rm /bigfile
将这两个命令放在一行上,如下所示:,这样可以最大程度地减少磁盘满时的时间,以防您不等待dd
完成。
我在装有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
我在评论中留下了链接,因此您可以(一定程度上)知道它是如何工作的。
编辑
这本身不是直接的答案,因为我要解决的是问题,而不是问题。该解决方案没有定期压缩映像,而是使用丢弃来自动删除主机的VM磁盘映像中未使用的块。
此解决方案需要支持连续TRIM的来宾文件系统。Arch Linux Wiki包含支持TRIM操作的文件系统列表。
FDE和cryptoroot明确不包括在内,因为存在安全问题,并且此问题的其他解决方案均不允许压缩。Arch Linux Wiki包含有关TRIM和dm-crypt设备的信息。
从理论上讲,这将适用于使用VDI存储的VBox主机上的所有Linux来宾。
在退出VBox且没有运行VM的情况下,通过在VM的配置文件中同时设置磁盘discard
和nonrotational
每个磁盘,为磁盘添加丢弃支持。这时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
使用手动修剪自由块fstrim
。fstrim
使用已安装的文件系统,而不是支持它的块设备。fstab
可以在每周cron中完成此操作,而不必在中设置连续丢弃。(建议对可能对TRIM的支持有问题的物理SSD每周进行cron计划,但这在这里不重要,因为底层SSD由主机OS处理。请参阅:ssd trim warning)。
fstrim /
fstrim /build
此时,VM内文件系统的大小和VM映像的大小应该非常接近。
经过测试:
我将其用于安装在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
希望能帮助到你 :)
我不想在OS中启用TRIM支持,因为每次删除数据都会强制将VDI文件中的数据压缩,从而使VDI文件位于经典旋转磁盘上时,来宾系统无法使用。对我来说,更好的方法是手工压实,例如每月一次。
在常规压缩期间,VDI文件内容将复制到新文件。这需要主机光盘上有一些(有时很大)可用空间。
我的解决方案与Andrew Domaszek所指出的类似。即使使用NTFS(Windows10),它也能很好地工作。
去做这个:
将基于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
启动机器
mount /dev/sda2 /mnt
dd if=/dev/zero of=/mnt/bigfile
rm /mnt/bigfile
fstrim -v /mnt
旧版(〜1997-2007)操作系统的重要说明
通常,先前给出的答案中的技术是有效的。但是,有一个非常重要的特殊情况。
在一段时间(也许是1997-2007年左右)的一段时间内,仍然是32位操作系统,但是已经使用了大于2GB的硬盘。结果,当尝试通过写入零文件来消耗所有可用空间时(应始终以root身份进行操作,以包括root的特权可用空间,其他人都无法接触),您可能会看到:
文件过大
而不是您的期望:
设备上没有剩余空间。
如果发生这种情况,您很可能达到了2GB的文件大小限制。这在当时很常见,因为许多文件操作返回的结果都是带符号的32位整数,因此负值可以报告错误代码。这实际上意味着无需特殊措施即可将偏移结果限制为2 ^ 31字节。
解决方法很简单:继续创建单独的,名称不同的清零文件,直到磁盘实际空间不足为止。
如果您希望在课堂上演示这种情况,那么使用带Red Hat Linux 7.0旧副本的4GB磁盘映像就足够了。