martedì 16 ottobre 2007

VirtualBox: compattare dischi virtuali ad espansione dinamica - guest Linux (1a parte)

Aggiornamento: continuate a leggere il post se siete interessati all'aspetto tecnico del problema, per la sua soluzione attualmente è più semplice e ricco di opzioni l'uso di CloneVDI.
____________________________________________________________________

Nel prologo sull'argomento avevamo inquadrato la problematica: quando liberiamo spazio sul disco rigido della macchina virtuale, il file vdi sull'host che lo contiene non si ridimensiona di conseguenza: occorre forzarne il ridimensionamento con un apposito comando, modifyvdi, disponibile solamente dalla console a linea di comando dell'host attraverso il gestore di comandi di VirtualBox, VboxManage.

Purtroppo però ciò non è sufficiente, occorre che sia soddisfatto un pre-requisito: lo spazio libero sul guest deve essere marcato a zero (il valore, non la cifra) prima che il comando possa agire su di esso compattandolo. Questo perché quando cancellate un file, questi non viene realmente cancellato, semplicemente lo spazio che occupa viene dichiarato libero in una apposita tabella.

I settori del disco rigido quindi, contengono ancora i dati, ed è per questo che il comando modifyvdi non riesce a fare il suo lavoro: può infatti agire solo su spazio realmente vuoto e non su quello dichiarato semplicemente come tale. Occorre un programma che svuoti per davvero lo spazio dichiarato libero.

VirtualBox non ha un comando interno per marcare a zero i settori liberi del disco rigido virtuale, ma niente paura, come scopriremo tra breve ciò non è un problema con un guest Linux. Quanto vedremo poi è identico per tutte le distribuzioni, anche se le immagini per forza di cose devono far riferimento ad una in particolare ed in questo caso si tratta di una Ubuntu. Cominciamo.

Avviate la macchina virtuale della vostra distribuzione Linux e aprite il file manager (l'analogo dell'Esplora risorse per intenderci). Se date un'occhiata alla cartella che rappresenta l'intero filesystem (fig. 1), vederete quanto spazio libero in questo momento vi è sul vostro disco rigido virtuale (guardate sotto il mouse), nella macchina di esempio ancora 15,4 GB.

Fig. 1 - Compattazione disco virtuale - spazio libero guest
fig. 1


Diamo un'occhiata alle dimensioni del corrispondente file vdi sull'host contenente il disco rigido virtuale. Ci saremmo aspettati un file dalla dimensioni di circa:

20 GB - 15,4 GB = 5,6 GB

ma come potete vedere, ve ne è uno da 7 GB (fig. 2). La discrepanza è dovuta al fatto che il file manager non vi sta mostrando tutto lo spazio realmente utilizzato, manca ad esempio quello del file di swap: in Windows questo è un file come tutti gli altri (C:\pagefile.sys), su Linux è una vera e propria partizione separata adibita, esclusivamente a questo scopo e con un suo specifico tipo di filesystem.

Fig. 2 - Compattazione disco virtuale - dimensione iniziale file VDI
fig. 2


Visto che ora sappiamo come copiare file dall'host tramite le cartelle condivise, ne possiamo approfittare per copiarci da lì dei file molto grandi; esempio: 6 file da 700 MB ottenuti copiando nella cartella condivisa, con 6 nomi diversi, la iso d'installazione di Ubuntu. Dalla cartella condivisa, copiamoli sul Desktop di Linux (fig. 3).

Fig. 3 - Compattazione disco virtuale - copia file da host a guest
fig. 3


Terminata la copia, date un'occhiata nel file manager alla spazio libero, è diminuito a (fig. 4):

15,4 GB - (6 * 700 MB) = ~11, 3 GB

Fig. 4 - Compattazione disco virtuale - spazio guest diminuito
fig. 4


Corrispondentemente anche il file vdi sull'host è cresciuto, anche se con delle discrepanze per via della diversa gestione dello spazio disco fra Linux e Windows (fig. 5).

Fig. 5 - Compattazione disco virtuale - file VDI cresciuto
fig. 5


Ora eliminate i file copiati sul vostro Desktop Linux e verificate che lo spazio libero sia tornato quello originale (fig. 6). Verificate poi le dimensioni del file vdi sull'host; sono restate quelle di fig. 5: come ci aspettavamo, non si è ridimensionato.

Fig. 6 - Compattazione disco virtuale - spazio guest iniziale
fig. 6


Bene, iniziamo allora a lavorare alla sua compattazione. Vi riassumo le fasi su Linux perché leggermente diverse da Windows, con dei passaggio in più:

- fase 1: creazione di un unico file contenente caratteri e grande quanto tutto lo spazio libero sul guest così da riempirlo completamente;
- fase 2: sovrascrittura del file con valori zero;
- fase 3: cancellazione del file;
- fase 4: compattazione del file vdi sull'hot.

Vediamole una ad una.

Fase 1: la prima cosa da fare è creare un file.

Per farlo, aprite la finestra del terminale (shell) è date questo comando (fig. 7):

touch /home/nomeutente/Desktop/filetuttizero

Il comando touch crea il file di nome “filetuttizero” nella cartella /home/nomeutente/Desktop. Guardate infatti il vostro Desktop, è comparso un file con questo nome.

Fig. 7 - Compattazione disco virtuale - creazione filetuttizero
fig. 7


In questo momento il file è vuoto, (provate a guardarne le dimensioni, è zero byte), riempiamolo di caratteri: per comodità lo riempiremo di caratteri zero (caratteri questa volta, non valori, questo lo faremo dopo con un altro comando) perché su Linux c'è un dispositivo virtuale che ce li fornisce “aggratis”. Sempre dalla vostra finestra di terminale, date il comando

cat /dev/zero > /home/nomeutente/Desktop/filetuttizero

che significa:

- cat sta per conCATenate, concatena 2 file fra loro;
- /dev/zero è il dispositivo virtuale che fornisce caratteri zero a tutto spiano;
- > è l'operatore di redirezione, prende ciò che lo precede, cat /dev/zero, ossia i caratteri zero che questi fornisce, e li manda su ciò che segue, cioè il file filetuttizero.

Andate adesso a prendervi un bel caffè mentre filetuttizero incamererà sempre più caratteri zero fino a saturare tutto lo spazio libero sul guest. Quando questo è avvenuto, nel terminale comparirà un messaggio del tipo di fig. 8:

cat: errore di scrittura: Niente spazio sul device.

Fig. 8 - Compattazione disco virtuale - errore spazio terminato
fig. 8


Controllate lo spazio libero del vostro guest nel file manager (fig. 9), è effettivamente terminato (0 byte di spazio libero).

Fig. 9 - Compattazione disco virtuale - spazio guest terminato
fig. 9


Idem se verificate le dimensioni del file vdi sull'host (fig. 10).

Fig. 10 - Compattazione disco virtuale - file VDI dimensione massima
fig. 10


Fase 2-3: riempiamo filetuttizero con dei valori zero (in questo momento contiene caratteri zero) ed infine lo cancelliamo (vi spiego tra poco perché).

Per farlo useremo un altro comando Linux: shred. Il suo compito è di sovrascrivere un file con una serie di caratteri casuali per il numero di volte che vogliamo. Quando ha finito l'ultima passata, possiamo aggiungere un'ulteriore passata di valori zero (proprio quello che ci serve) e infine cancellare il file.

Dalla finestra di terminale date il comando:

shred -f -n0 -z -v -u /home/occhipervinca/Desktop/filetuttizero

f = force, forza i permessi sui file affinché possiate comunque eseguire sempre il comando;
n = 0, non ci interessa riempire
filetuttizero di caratteri casuali, perciò gli indichiamo di fare zero passate di scrittura di caratteri casuali, cioè nessuna;
z = riempie di valori zero il file dopo l'ultima passata, non vi sono passate precedenti (n = 0), perciò lo fa subito;
v = verbose, modalità chiacchierona del comando, vi aggiorna man mano su quello che sta facendo, giusto per capire a che punto siamo;
u = il file alla fine di tutti i passaggi viene cancellato.

In fig. 11 il comando ha iniziato il suo lavoro, approfittatene per un altro caffè! ;-)

Fig. 11 - Compattazione disco virtuale - comando shred
fig. 11


Quando ha terminato, a terminale comparirà il messaggio di fig. 12 o uno analogo: il file è stato rimosso.

Fig. 12 - Compattazione disco virtuale - comando shred filetuttizero rimosso
fig. 12
Sappiamo già che il file non viene realmente cancellato ma solo dichiarato libero lo spazio che occupava, spazio che è colmo di valori zero perché questo era il suo contenuto immediatamente prima di essere cancellato: proprio quello che serve al comando di compattazione modifyvdi per funzionare.
Fase 4: è arrivato finalmente il momento di compattare il file vdi sull'host: ora è possibile, la precondizione che lo spazio libero sul disco rigido virtuale fosse marcata a zero è soddisfatta. Aprite una finestra DOS (pulsante start --> Esegui --> scrivete cmd e date invio). Al suo interno date questo comando, doppi apici compresi anche su nomefile se questo contiene spazi vuoti:

"C:\Programmi\innotek VirtualBox\VBoxManage" modifyvdi “nomefile”.vdi compact

Nel caso della nostra macchina virtuale di esempio diventa:

"C:\Programmi\innotek VirtualBox\VBoxManage" modifyvdi Ubuntu7_04.vdi compact

Mentre il comando fa il suo lavoro, vi spiego la sintassi per chi non la ricorda o non ha seguito la 2a parte del post:

- intanto i doppi apici anche qui servono ove ci siano spazi vuoti. Normalmente la linea di comando interpreta gli spazi vuoti come la fine di qualcosa; se non mettiamo i doppi apici, C:\Programmi\innotek VirtualBox\VBoxManage non viene interpretata come una cosa unica ma viene presa solo la prima parte, cioè C:\Programmi\innotek e li si ferma dando errore. Stessa cosa con il nome del file vdi, i doppi apici sono obbligatori solo se il nome del file vdi presenta spazi al suo interno;

- VBoxManage è il comando che lancia il manager a linea di comando di VirtualBox, serve a dare da linea di comando tutti i comandi che normalmente date dall'interfaccia grafica, e altri che l'interfaccia grafica non implementa ancora ma sono comunque disponibili da linea di comando;

- modifyvdi è il comando impartito a VBoxManage, gli dice che volete modificare il file nomefile.vdi;

- compact dice che la modifica che volete effettuare sul file vdi è la sua compattazione.

Nel frattempo la compattazione dovrebbe essere finita, in fig. 13 il risultato: come potete vedere, il file vdi è tornato all'incirca alle sue dimensioni iniziali.

Fig. 13 - Compattazione disco virtuale - file VDI compattato
fig. 13


Wooww... post lunghissimo, frutto della decisione di rendere indipendenti fra loro i post dedicati ai guest Linux da quelli dedicati ai guest Windows. Per far questo ho duplicato in parte i contenuti, così da
non costringervi a salti dall'uno all'altro post e favorire la comprensibilità dell'argomento; spero di esserci riuscito. :-)

Ok, è tutto, non mi resta che augurarvi, una serena compattazione!

@:\>

____________________________________________________________________
Aggiornamento del 25/10/2007:

come ha evidenziato nei commenti Michele Benvegnù, questa soluzione che è
semplice e immediata da realizzare su tutte le distribuzioni Linux, è ampiamente inefficiente nell'uso dello spazio disco e del tempo di elaborazione. Così, quello che doveva essere un post unico, si è in realtà trasformato nel primo dedicato all'argomento. Ed ora, il link alla 2a parte.

@:\>

2 commenti:

  1. C’è qualcosa che non mi convince nel metodo esposto per compattare i dischi virtuali ad espansione dinamica nel guest Linux; premetto che di Linux sono un totale neofita, ma credo sia possibile utilizzare metodi più efficienti; anzi, in teoria ciò è sicuramente possibile, bisogna solo capire come implementarlo.
    Riassumiamo.
    Consideriamo un disco ad espansione dinamica ad esempio di 16 GB, con 5 GB occupati dopo l’installazione del sistema operativo, e 11 liberi. Il file VDI occupa pertanto 5 GB.
    Dopo avere copiato alcuni file per un totale di 5 GB, lo spazio occupato sale a 10 GB, ed altrettanto la dimensione del file VDI; dopo aver cancellato questi file, lo spazio occupato torna ad essere 5 GB, mentre il file VDI rimane invariato a 10 GB.
    Tutte cose già dette e ridette, accuratamente sviscerate nei post precedenti da GiornaleDiSistema.
    Ora il nostro disco rigido del nostro esempio contiene:
    • 5 GB di dati realmente presenti
    • 5 GB di dati cancellati, dichiarati liberi dal SO, ma contenenti byte realmente scritti, diversi da zero (che noi dovremo sovrascrivere con zeri prima di compattare il VDI)
    • 6 GB liberi, mai utilizzati. Questo spazio, in un disco virtuale a dimensione fissa o in un HD fisico, reale, non essendo mai stato utilizzato, è già al valore zero; in un disco virtuale ad espansione dinamica, semplicemente … non esiste (è per questo motivo che il file VDI è grande solo quanto lo spazio effettivamente occupato).
    Il metodo esposto in questo post consiste nel creare un file e poi riempirlo con zeri sino ad occupare tutto lo spazio libero disponibile. Il metodo non distingue tra lo spazio precedentemente allocato (e quindi non zero) e lo spazio mai usato (e quindi già a zero). Cosa cambia? Semplice: così dobbiamo sovrascrivere con zeri tutto lo spazio teoricamente disponibile sul disco virtuale ad espansione dinamica; dopo questa operazione, il file VDI nel sistema host avrà una dimensione pari alla dimensione massima teorica assegnata al disco virtuale.
    E non è un problema di poco conto: infatti, i dischi ad espansione dinamica permettono di creare dischi molto grandi per eventuali esigenze future, sapendo che, almeno inizialmente, non ruberanno troppo spazio. Ad esempio, per il mio guest Ubuntu, ho assegnato un disco di 64 GB; utilizzando la metodica proposta, mi trovo ad avere un file VDI che ha davvero (almeno fino a che non lanciamo modifyvdi) una dimensione di 64 GB: un bel lavoraccio per le testine del mio HD scrivere 64 GB di zeri (in realtà 59 GB, in quanto 5 sono veramente occupati); soprattutto tenendo conto che basterebbe scriverne solamente 5 GB, pari allo spazio precedentemente allocato e poi cancellato. Senza contare che abbiamo davvero bisogno di 64 GB realmente liberi sull’HD dell’host.
    SDelete.exe, il piccolo programmino a linea di comando che abbiamo utilizzato all’uopo nel guest Windows (vedi il post “VirtualBox: compattare dischi virtuali ad espansione dinamica (2 parte)” è molto più efficiente, e correttamente si limita a sovrascrivere con zeri solamente lo spazio precedentemente allocato (5 GB nel nostro esempio); ed in effetti, dopo aver lanciato SDelete il file VDI non ha un temporaneo aumento delle sue dimensioni.
    In conclusione, sarebbe necessario trovare anche per Linux un programmino in grado di scrivere a zero solo la parte precedentemente occupata da dati. Io non saprei da che parte cominciare, ma sicuramente non sarà difficile trovare qualcuno che possa farlo nella vasta comunità open source.
    Per finire, una piccola considerazione: sarebbe doveroso per Innotek provvedere a fornire questi programmini nelle guest additions, ed altrettanto sarebbe opportuno inserire il comando modifyvdi nell’interfaccia grafica di VirtualBox, anziché lasciarlo disponibile solamente dalla linea di comando.

    RispondiElimina
  2. Ciao Michele! :-)

    Analisi condivisa al 100%. Infatti il post è un "working in progress"... una sperimentazione sul campo con Linux proponendo una soluzione che è immediata da implementare perché utilizza comandi a disposizione in qualunque distribuzione. Situazione in cui l'utente ha scelto di dare dimensione davvero generose al disco rigido virtuale (la modalità dinamica è lì apposta), il limite intrinseco del comando shred che abbisogna di un file su cui agire, il tutto unito alla mia voglia di sperimentare il dispositivo virtuale fornitore di zero "aggratis" e la redirezione dell'input/output... insomma,il patatrac è servito! ;-)

    Questo metodo infatti non brilla certo per efficienza nella gestione dello spazio disco, ne per i suoi tempi. Se con un disco rigido virtuale da 20 GB abbiamo il tempo di un caffè, con 64 GB possiamo anche fare la pausa pranzo!

    Presto una soluzione molto più efficiente. ;-)

    Ciao ciao.
    @:\>

    RispondiElimina

L'autore del commento si assume la totale responsabilità del suo contenuto. Commenti ritenuti offensivi o non attinenti potranno essere cancellati.