SD-Karten-Images (Backups) richtig verkleinern

Wer sein System einmal eingerichtet hat, der profitiert davon, ein Backup der gesamten SD-Karte anzufertigen. Eine 1:1-Kopie der SD-Karte ist jedoch unpraktisch, da diese Images dann nur auf Karten mindestens gleicher Größe zurückkopiert werden können und je nach System ist der Großteil der root-Partition unbenutzt, sodass der leere Speicherplatz dann auf dem Image unnötig Speicher belegt.

Hier zeige ich, wie man diese Images möglichst klein bekommt, und zwar ohne sie lediglich im engeren Sinn zu komprimieren. Benötigt wird nur ein Linux-Rechner, auf dem GParted installiert ist, sowie das unpraktische, große Image (hier: Image eines Raspberry Pi B mit dem Dateinamen „ArchLinuxARM-rpi-20150823.img“). Diese Anleitung ist im Wesentlichen nur eine angepasste Übersetzung von [1].

Loopback-Device anlegen

Zunächst als root anmelden, dann Loopback-Devices aktivieren (falls nicht bereits automatisch geschehen):

modprobe loop

Das nächste freie Device wird uns mit folgendem Kommando angezeigt:

losetup -f

In diesem Fall wird uns /dev/loop0 angeboten. Damit erstellen wir nun ein Device auf dem Image:

losetup /dev/loop0 ArchLinuxARM-rpi-20150823.img

Da das Image mehrere Partitionen enthält und wir an diesen arbeiten wollen, muss dem Kernel mitgeteilt werden, dass wir dies vorhaben:

partprobe /dev/loop0

Partitionsgröße mit GParted ändern

Jetzt wird GParted gestartet, um die Größe der root-Partition zu ändern:

gparted /dev/loop0

Es sollte sich ein Fenster öffnen, das in etwa wie folgt aussieht:

GParted-Startfenster

Die ext4-Partition ist die root-Partition, die wir verkleinern wollen. Ein Rechtsklick auf diese Partition eröffnet und die entsprechende Schaltfläche. Folgendes Fenster zeigt sich danach:

Partitionsgroesse aendern

Den rechten Begrenzungsbalken verschieben wir so weit nach links wie möglich; es sollten aber etwa 200MB Luft gelassen werden, ansonsten quittiert GParted das ganze später mit einer Fehlermeldung und fordert zum Korrigieren der Größe auf. Das Hauptfenster sollte dann etwa so aussehen:

GParted-Startfenster neu

Jetzt müssen die Änderungen noch übernommen werden. Nach erfolgreichem Abschluss kann GParted geschlossen und das Loopback-Device wieder gelöscht werden:

losetup -d /dev/loop0

Das Image beschneiden

Als erstes müssen wir mittels fdisk herausfinden, wo genau im Abbild der nicht zugeteilte Speicher beginnt:

fdisk -l ArchLinuxARM-rpi-20150823.img

Die Ausgabe sieht etwa so aus:

Disk ArchLinuxARM-rpi-20150823.img: 3,7 GiB, 3980394496 bytes, 7774208 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x8ae06106

      Device Boot                Start      End   Blocks  Id  System
ArchLinuxARM-rpi-20150823.img1    2048   206847   204800   c  W95 FAT32
ArchLinuxARM-rpi-20150823.img2  206848  2459647  2252800  83  Linux

Wichtig sind hierbei zwei Dinge: Die Blockgröße beträgt 512 Bytes und die interessierende zweite Partition endet nach Block 2459647, also nach dem 512*2459647. Byte der Datei, danach folgt der nicht zugeteilte Speicher, den wir abschneiden wollen. Dies tun wir mittels truncate-Befehl:

truncate --size=$[(2459647+1)*512] ArchLinuxARM-rpi-20150823.img

Das wars, das Image ist nun wesentlich kleiner und passt u.U. auch auf kleinere SD-Karten.

root-Partition nach Wiederherstellung erweitern (Raspberry Pi B)

Wenn das Image auf eine leere SD-Karte übertragen wurde, sollte die root-Partition noch expandiert werden. Dies kann über einige wenige Befehle erledigt werden:

echo -e "p\nd\n2\nn\np\n2\n\n\nw" | fdisk /dev/mmcblk0
reboot
resize2fs /dev/mmcblk0p2