Inhaltsverzeichnis

Tutorial - Verkleinern eines dd-Disk-Images

Version Status Datum Author URL
0.1 Erster Entwurf 24.05.2020 Egil Rüefli
0.2 Ergänzungen TT.MM.JJJJ Vorname Nachname
1.0 Review und Freigabe TT.MM.JJJJ Vorname Nachname

1. Kurzfassung

Ausgangspunkt für dieses Tutorial war ein mit dem Befehl dd erzeugtes Disk-Image, das auf eine andere Maschine kopiert werden sollte. Für den Transfer musste das Image so effizient wie möglich komprimiert werden. Da auf dem Image neben den Nutzdaten auch bereits gelöschte, aber noch nicht überschriebene Dateien vorhanden waren, wurde es vor dem Komprimieren zunächst mit einer grossen Datei gefüllt, die lauter Nullen enthielt. Diese Datei wurde im Anschluss wieder gelöscht. Das so gesäuberte Image komprimierte signifikant besser als das Original-Image.

2. Tutorial

Vor dem Komprimieren eines Disk-Images muss sichergestellt werden, dass der freie Speicherplatz auf dem Image auch wirklich frei ist und nicht noch gelöschte Files enthält [(https://superuser.com/questions/610819/how-to-resize-img-file-created-with-dd)]. Dies erreicht man, indem man ein grosses File erzeugt, das nur aus Nullen besteht, und dieses File danach wieder löscht. Als erstes wird das Image mit dem Befehl losetup –find –partscan foo.img als loopback-device erstellt (sollte das Image keine Partitionstabelle enthalten, kann es direkt mit mount -o loop foo.img /mnt gemountet werden). Der Befehlt lsblk findet die ID des entsprechenden Geräts (hier das device loop0). In der for-Schleife werden die Partitionen des loopback-devices einzeln gemountet, das Nullen-File mit dd geschrieben und danach wieder gelöscht. Am Schluss wird auch das loopback-device mit losetup –detach /dev/loop0 wieder aufgelöst.

# losetup --find --partscan foo.img
# lsblk
NAME      MAJ:MIN RM    SIZE RO TYPE MOUNTPOINT
loop0       7:0    0   4096M  0 loop 
├─loop0p1 259:0    0   2048M  0 loop 
└─loop0p2 259:1    0   2048M  0 loop 
# for part in /dev/loop0p*; do
    mount $part /mnt
    dd if=/dev/zero of=/mnt/filler conv=fsync bs=1M
    rm /mnt/filler
    umount /mnt
  done
dd: error writing ‘/mnt/filler’: No space left on device
dd: error writing ‘/mnt/filler’: No space left on device
# losetup --detach /dev/loop0

Mit gzip foo.img kann das Image danach komprimiert werden. Selbst bei einer niedrigen Kompressionsrate komprimiert eine Serie von Nullen sehr gut.

3. Testing

3.1 Test

Testfall Nr. #1
Beschreibung Grössenvergleich komprimiertes Original-Image vs. mit Null-File gesäubertes Image
Vorgehen 1. Komprimieren des Original-Images (der Befehl time wird vorangestellt, um die für die Ausführung des zip-Befehls benötigte Zeit zu messen) → Kompression: 50%
Voraussetzung / Umfeld Der Test wird auf einem Debian 6 durchgeführt. Das Disk-Image stammt von einer XEN-VM.
Erwartetes Resultat Das mit einem Null-File gesäuberte Image ist nach der Kompression signifikant kleiner als das komprimierte Original-Image
OK / nicht OK OK
Aufgetretene Fehler / Bemerkungen Keine

4. Auswertung

Auf dem Debian System fehlten dem Befehl losetup der Parameter –partscan. Das Image wurde deshalb anders als im Tutorial angegeben direkt mit mount -o loop foo.img /mnt gemountet. Das funktioniert, weil das Original-Image über keine Partitionstabelle verfügt. Wie lange die Komprimierung eines 40G Images auf einem Dual Core AMD Opteron™ Processor 275-System mit 2 SAS-Platten (WD6000BKHG-02A29) im Raid 1 (Raid-Controller: LSI Logic / Symbios Logic SAS1064 PCI-X Fusion-MPT SAS) dauert, wurde unterschätzt.

5. Quellenverzeichnis