Come compattare le dimensioni del file VDI di VirtualBox?


301

Ho una VM VirtualBox che ha configurato una dimensione del disco rigido molto grande (più grande dell'host). Per errore, un programma sulla VM ha generato molti file di registro e la dimensione del file VDI continua a crescere fino a quando non c'è spazio sull'host.

Ora ho eliminato i file di registro ma le dimensioni del file VDI non si riducono dopo l'uso VBoxManage.exe modifyhd "C:\Virts\mybox-i386.vdi" compact

C'è un modo per compattare davvero la dimensione del file VDI? Grazie!

Risposte:


507

Devi fare i seguenti passi:

  1. Esegui deframmentazione nel guest (solo Windows)
  2. Annulla spazio libero:

    Con un guest Linux esegui questo:

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

    O:

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

    Con un guest Windows , scarica SDelete da Sysinternals ed esegui questo:

    sdelete.exe c: -z
    

    (sostituire C: con la lettera di unità del VDI)

  3. Arrestare la VM guest

  4. Ora esegui il modifymediumcomando di VBoxManage con l' --compactopzione:

    Con un host Linux esegui questo:

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

    Con un host Windows eseguire questo:

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

    Con un host Mac eseguire questo:

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

Questo riduce le dimensioni del VDI.


15
Per la persona successiva, il mio comando è finito così: "C: \ Programmi \ Oracle \ VirtualBox \ VBoxManage.exe" modificahd "C: \ Users \ daniel \ VirtualBox VMs \ .... \ thedisk.vdi" - -compatto
Daniel,

36
Secondo lo zerofree Linux pagina man di utilità ( manpages.ubuntu.com/manpages/natty/man8/zerofree.8.html ), zerofree dovrebbe essere migliore di dd per questo lavoro. dd non sarebbe stato raccomandato perché "è lento", "fa crescere (temporaneamente) l'immagine del disco nella sua massima estensione", "usa (temporaneamente) tutto lo spazio libero sul disco, quindi altre azioni di scrittura simultanee potrebbero non riuscire". Zerofree è disponibile su Ubuntu Linux tramite apt , oppure puoi compilarlo da solo.
Dakatine,

27
È divertente che la manpage di zerofree affermi che con dd altre scritture simultanee falliranno, ma zerofree ha bisogno che il filesystem sia montato in sola lettura! * duh *
Madarco,

7
Suggerimento: posiziona i due comandi su una riga in questo modo: dd ...; rm /bigfilequesto ridurrà al minimo il tempo con un disco intero nel caso in cui non aspetti il ddcompletamento.
jlh

21
@Dakatine Utilizzando VirtualBox 4.3.10, il file di immagine del disco non è cresciuto al massimo. VirtualBox è abbastanza intelligente da non disturbare a scrivere tutti i blocchi zero sul disco fisico.
jlh

12

Sono su un host Windows 7 con guest Windows, ecco un file batch che ho scritto per compattare tutti i VDI in un albero di cartelle

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

Ho lasciato i collegamenti nei commenti in modo da poter (in qualche modo) dire come funziona.

modificare

Bene, dopo tutto ciò, ho provato lo strumento CloneVDI e ha fatto un buon lavoro in molto meno tempo e con un clic.


5
Penseresti che su questo tipo di sito ci sarebbe una sorta di evidenziazione della sintassi per DOS ma no. Sembra molto più bello in Notepad ++
Bloke CAD

1
@CAD_bloke che richiederebbe un motore di analisi e quando consideri il numero di lingue diverse pubblicate su SE stai guardando un progetto ENORME. Pensa solo a quante versioni e dialetti di DOS ci sono, ad esempio, e prima ancora di arrivare a Linux, ecc.
Caltor,

Ottimo punto Ironia della sorte è evidenziato sull'app iOS di scambio di stack.
Bloke CAD,

2
Sì, CloneVDI è un modo molto migliore e più veloce per uso personale
VarunAgw

6

Ospite Debian su host Windows usando discard / TRIM.

Questa non è una risposta diretta di per sé, poiché sto affrontando il problema, non la domanda. Invece di compattare periodicamente l'immagine, questa soluzione utilizza scarta per rimuovere automaticamente i blocchi non utilizzati nell'immagine del disco della macchina virtuale dell'host.

Questa soluzione richiede un filesystem guest che supporti il ​​TRIM continuo. La wiki di Arch Linux ha un elenco di filesystem che supportano le operazioni TRIM .

FDE e cryptoroot non sono specificamente coperti, in quanto vi sono problemi di sicurezza e nessuna delle altre soluzioni a questa domanda consentirebbe la compattazione. La wiki di Arch Linux contiene informazioni sui dispositivi TRIM e dm-crypt .

In teoria, questo funzionerà per tutti i guest Linux su host VBox che usano l'archiviazione VDI.

Configurazione host

Con VBox chiuso e nessuna VM in esecuzione, aggiungere il supporto di eliminazione ai dischi impostando entrambi discarde nonrotationalper ciascun disco nel file di configurazione per la VM. Al momento discardnon si trova nella GUI, ma nonrotationalè esposto come casella di controllo "Unità a stato solido". (rif: forum vbox, supporto scarta )

<AttachedDevice discard="true" nonrotational="true" type="HardDisk" [..other options..] >

Avviare la VM e verificare che il supporto TRIM sia abilitato:

sudo hdparm -I /dev/sda | grep TRIM

Configurazione ospite

Se LVM è in uso, modificare l'impostazione di eliminazione in /etc/lvm/lvm.conf. (ref: debian wiki, esempio lvm.conf )

devices {
...
    issue_discards = 1
}

In fstab, aggiungi l' discardopzione al filesystem che desideri scartare automaticamente (rif: debian wiki, esempio 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

Rimontare i filesystem per farli scegliere le loro nuove opzioni.

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

Taglia manualmente i blocchi gratuiti ora con fstrim. fstrimusa il filesystem montato, non il dispositivo a blocchi che lo supporta. Invece di impostare uno scarto continuo fstab, questo potrebbe essere fatto su un cron settimanale. (Il cron settimanale è raccomandato per gli SSD fisici che potrebbero avere un supporto discutibile per TRIM, ma questo non è rilevante qui poiché gli SSD sottostanti sono gestiti dal sistema operativo host. Vedi: avviso di ssd trim ).

fstrim /
fstrim /build

A questo punto, la dimensione dei filesystem all'interno della VM e la dimensione delle immagini della VM dovrebbero avere un valore abbastanza vicino.

Testato con:

  • Guest1: Debian 8.7, kernel: linux 4.8 grsec da backport, filesystem: ext4
  • Guest2: Debian 9 RC2, kernel: linux 4.9, filesystem: ext4
  • Host1: VBox 5.1.14, Win7, immagine fmt: VDI
  • Host2: VBox 5.1.14, Win8.1, immagine fmt: VDI

2

Per MacOS Guest, procedere come segue:

  1. Annullare lo spazio libero nel sistema guest:

    diskutil secureErase freespace 0 "/Volumes/Macintosh HD"
    

    (sostituisci / Volumes / Macintosh HD con il nome dell'unità)

  2. Arrestare la VM guest

  3. Eseguire questo comando per ridurre la dimensione dell'immagine del disco VDI

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

    O

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

1

Lo uso per la mia immagine VDI montata su Debian virtuale in Windows VirtualBox. Non è una soluzione generale, ma dovrebbe almeno darti un'idea di ciò che faccio.

Comandi in Debian:

root@debian:~# lsblk  # show partitions
NOME MAJ: TAGLIA MIN. TIPO MO MOUNTPOINT 
sdb 8:16 0 128G 0 disco 
└─sdb1 8:17 0 128G 0 part / mnt / web # QUESTA È LA SEZIONE DI INTERESSE!
sda 8: 0 0 64G 0 disco 
S─sda1 8: 1 0 61,4G 0 parte / 
S─sda2 8: 2 0 1K 0 parte 
S─sda5 8: 5 0 2,7G 0 part 
[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

Comandi in Windows:

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

Spero che sia d'aiuto :)


1

Non voglio abilitare il supporto TRIM nel sistema operativo, poiché ogni eliminazione dei dati forzerà la compattazione dei dati nel file VDI, rendendo il sistema guest inutilizzabile quando il file VDI si trova sul disco rotazionale classico. Per me è meglio eseguire la compattazione a mano, ad esempio una volta al mese.

Durante la normale compattazione, il contenuto del file VDI viene copiato nel nuovo file. Ciò richiede dello spazio libero (a volte grande) sul disco host.

Ho una soluzione simile a quella indicata da Andrew Domaszek. Funziona molto bene anche con NTFS (Windows10).

Per farlo:

  • crea una nuova macchina virtuale che si avvia con GParted Live CD (puoi usare la tua distribuzione Linux preferita).
  • Modifica le impostazioni della macchina e imposta il controller del disco SATA
  • Aggiungi file VDI esistenti che vuoi compattare
  • Modifica i dischi basati su VDI in modo che siano visibili come SSD con supporto TRIM:

    VBoxManage storageattach "gpared live" --storagectl "SATA" --port 0 --discard on --nonrotational on
    VBoxManage storageattach "gpared live" --storagectl "SATA" --port 1 --discard on --nonrotational on
    
  • avviare la macchina

  • Nella shell principale di Linux, montare la partizione NTFS mount /dev/sda2 /mnt
  • zero spazio libero dd if=/dev/zero of=/mnt/bigfile
  • rm /mnt/bigfile
  • impone la compattazione di VDI senza creare un nuovo file: fstrim -v /mnt

0

Un trucco molto accurato per integrare la risposta accettata è che puoi cavartela senza fare alcuna compattazione dopo aver azzerato lo spazio ospite, utilizzando un file system compresso sull'host (ad esempio selezionando per comprimere la cartella di unità virtuali su proprietà NTFS in un Host di Windows). Questo in effetti ha il vantaggio di risparmiare molto più spazio perché i sistemi operativi tendono a contenere molti file di testo o binari ripetitivi (ad esempio un'unità guest da 30 GB con 15 GB di spazio azzerato può trasformarsi in 4 GB sull'unità host).

Le avvertenze includono che l'accesso all'unità sull'hardware reale potrebbe aumentare e vi è un leggero aumento dell'utilizzo della CPU.


0

NOTA IMPORTANTE PER I SISTEMI OPERATIVI LEGACY (~ 1997-2007)

In generale, le tecniche nelle risposte precedentemente fornite sono valide; TUTTAVIA, c'è un caso speciale molto importante.

Per un periodo di alcuni anni - forse 1997-2007 o giù di lì - i sistemi operativi a 32 bit erano ancora la norma, ma erano già in uso dischi rigidi di dimensioni superiori a 2 GB. Di conseguenza, quando si tenta di consumare tutto lo spazio libero scrivendo un file di zero (che deve sempre essere eseguito come root, per includere lo spazio libero privilegiato di root, che nessun altro può toccare), è possibile che venga visualizzato:

File troppo grande

invece di quello che ti aspetti:

Nessuno spazio lasciato sul dispositivo.

In questo caso, molto probabilmente hai raggiunto un limite di dimensioni del file di 2 GB. Questo era comune all'epoca perché molte operazioni sui file restituivano risultati in numeri interi a 32 bit con segno, in modo che valori negativi potessero riportare codici di errore. Ciò significava che i risultati di offset erano limitati a 2 ^ 31 byte senza misure speciali.

La soluzione è semplice: continua a creare file di azzeramento separati e con nomi diversi fino a quando il disco si esaurisce effettivamente.

Se sei un istruttore che desidera dimostrare questa situazione per una classe, è sufficiente un'immagine del disco da 4 GB con una vecchia copia di Red Hat Linux 7.0.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.