Raspberry Pi: SD-Karten-Image verkleinern

Prof. Jürgen Plate

Raspberry Pi: SD-Karten-Image verkleinern

Manchmal muss man das Image auf einer SD-Karte verkleinern, weil man beim Kopieren des Images feststellt, dass die neue Karte um einige hundert Bytes kleiner ist, als die aktuelle.

Natürlich ist das Ändern der Größe eines Dateisystems im laufenden Betrieb eine sehr gefährliche Sache, weil man nicht sicher sein kann, ob beim Aufruf von resize2fs vorhandene Dateien nicht doch beschädigt würden. Deshalb machen Sie auf jeden Fall einen Backup des Kartenimages.

Als Erstes nehmen Sie die Verkleinerung des Linux-Dateisystems mit resize2fs vor und danach erst verkleinern Sie die zugehörige Partition mit fdisk. Nur in dieser Reihenfolge bleibt das Dateisystem auf Linux unbeschädigt.

Sie können resize2fs nicht auf einem gemounteten Laufwerk ausführen, also nicht auf der SD-Karte, die gerade in Ihrem RasPi steckt. Daher muss dieser Schritt auf einem anderen Linux-Rechner erfolgen, der über einen SD-Kartensteckplatz verfügt. Zur Not kann das auch Ihr Windows-PC sein. Sie besorgen sich einfach ein CD-Image von Ubuntu, Knoppix oder einer anderen Linux-Distribution. Von der CD können Sie Linux zum Ausprobieren starten, ohne Änderungen an der Windows-Platte vornehmen zu müssen. Noch praktischer ist es, den Raspberry selbst zu verwenden. Dazu brauchen Sie nur einen USB-Adapter für SD-Karten, der in den RasPi gesteckt wird. Sie stellen eine Kopie der aktuellen SD-Karte her und stecken diese Kopie dann in den SD-Adapter. Alles Weitere geschieht dann mit dieser Kopie. Die Bearbeitung der SD-Karte auf einem Linux-System hat noch einen weiteren, gravierenden Vorteil.

Der Win32DiskImager, der häufig verwendet wird, um SD-Karten zu kopieren, kopiert leider immer die gesamte SD-Karte in ein Image auf der Platte, das dann natürlich nicht auf die kleinere Karte passt, selbst wenn das "echte" Dateisystem viel kleiner ist. Daher wird eine Kopie auf eine etwas kleinere SD-Karte immer noch fehlschlagen. Bei einem Linux-System zur Verfügung haben, können Sie das Programm dd verwenden, um beliebige Image-Größen zu erzeugen.

Nun geht es los. Zuerst müssen Sie die maximale Größe des Dateisystems bestimmen, das für Ihre Wahl der SD-Kartenkapazität sinnvoll ist. Dazu wird zuerst die aktuelle Größe der Partitionen ermittelt. Das geht einfach mit dem Kommando lsblk - "list block devices" (Kommando fett gedruckt):

lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
mmcblk0     179:0    0  7,5G  0 disk
|-mmcblk0p1 179:1    0   56M  0 part /boot
`-mmcblk0p2 179:2    0  7,4G  0 part /

Es gibt also zwei Partitionen, /dev/mmcblk0p1 und /dev/mmcblk0p2. Daraus kann man den Namen der Platte (raw-device) erschliessen: /dev/mmcblk0 . Nun kann man sich die Partitionstabelle ausgeben lassen (Kommando fett gedruckt):
sudo fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/mmcblk0: 7,5 GiB, 8010072064 bytes, 15644672 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
Disklabel type: dos
Disk identifier: 0x0002c262

Device         Boot  Start      End  Sectors  Size Id Type
/dev/mmcblk0p1        8192   122879   114688   56M  c W95 FAT32 (LBA)
/dev/mmcblk0p2      122880 15523839 15400960  7,4G 83 Linux


Command (m for help): q
Mit "p" lassen Sie sich die Partitionstabelle anzeigen und mit "q" verlassen Sie das Programm wieder.

Notieren Sie Start- und Endesektor der Linux-Partition (/dev/mmcblk0p2). Im Beispiel sind dies 122880 und 15523839. Nun überlegen Sie, um wieviel Sie die Partition verkleinern wollen. Der neue Endesektor könnte beispielsweise 15000000 sein.

Nun kommt die Kopie ins Spiel, die entweder im SD-Adapter des RasPi oder im SD-Kartenleser des Desktop-PCs steckt. Das weitere Vorgehen ist bei beiden Varianten genau gleich. Auch hier wird zuerst der Name der SD-Karte im Dateisystem ermittelt. Dazu geben Sie wider das Kommando lsblk ein. Im folgenden Beispiel wurde ein SD-Adapter am RasPi verwendet (Kommando fett gedruckt):

lsblk
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdc           8:32   1  7,4G  0 disk
|-sdc1        8:33   1   63M  0 part /media/usb
`-sdc2        8:34   1  7,1G  0 part
mmcblk0     179:0    0  7,5G  0 disk
|-mmcblk0p1 179:1    0   56M  0 part /boot
`-mmcblk0p2 179:2    0  7,4G  0 part /
In der ersten Zeile sieht man, dass der Name der Platte sdc lautet und der Pfad demnach /dev/sdc ist. Zuerst werden die Partitionen der SD-Karte ausgehängt und dann die Linux-Partition verkleinert. Beim Kommando resize2fs wird hier die neu gewählte Größe eingegeben:
sudo umount /dev/sdc1
sudo umount /dev/sdc2
sudo resize2fs -f /dev/sdc2 15000000s
Eventuell kommt beim Aushängen die Fehlermeldung "umount: /dev/sdc2: not mounted", was nicht weiter stört.

Nun kann wieder fdisk angewendet werden (Kommando fett gedruckt). Wichtig sind die Zahlenwerte bei der neu angelegten Partition. Der Startsektor muss der gleiche sein, wie vorher (im Beispiel 137216). Der Endesektor ist unsere neu gewählte Länge (15000000).

sudo fdisk /dev/sdc

Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/sdc: 7,4 GiB, 7948206080 bytes, 15523840 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
Disklabel type: dos
Disk identifier: 0x93548501

Device     Boot  Start      End  Sectors  Size Id Type
/dev/sdc1         8192   137215   129024   63M  c W95 FAT32 (LBA)
/dev/sdc2       137216 15523839 15386624  7,3G 83 Linux


Command (m for help): d
Partition number (1,2, default 2): 2

Partition 2 has been deleted.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (2048-15523839, default 2048): 137216
Last sector, +sectors or +size{K,M,G,T,P} (137216-15523839, default 15523839): 15000000

Created a new partition 2 of type 'Linux' and of size 7,1 GiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Keine Angst. Das Löschen und neu anlgen der zweiten Partition läßt die Daten völlig unberührt. Nun lassen Sie noch einen Check über die geänderte Partition laufen:
sudo e2fsck /dev/sdc2
e2fsck 1.42.12 (29-Aug-2014)
Die Größe des Dateisystems (laut Superblock) ist 1875000 Blöcke.
Die physikalische Größe des Gerätes ist 1857848 Blöcke.
Entweder ist der Superblock oder die Partionstabelle beschädigt!
Abbrechen? nein
/dev/sdc2 enthält ein fehlerhaftes Dateisystem, Prüfung erzwungen.
Durchgang 1: Inodes, Blöcke und Größen werden geprüft
Durchgang 2: Verzeichnisstruktur wird geprüft
Durchgang 3: Verzeichnisverknüpfungen werden geprüft
Durchgang 4: Referenzzähler werden überprüft
Durchgang 5: Zusammengefasste Gruppeninformation wird geprüft
/dev/sdc2: 134421/462144 Dateien (0.1% nicht zusammenhängend), 999413/1875000 Blöcke
Nun ist wirklich alles in trockenen Tüchern. Für den finalen Test wird der Raspberry jetzt heruntergefahren und Sie booten mit der gerade erzeugten SD-Karte. Diese wird ganz normal als mmcblk0 eingebunden. Wenn alles läuft, haben Sie jetzt ein eine SD-Karte mit verkleinertem Dateisystem.

Nun ist die letzte Herausforderung zu meistern: Das verkleinerte System auf eine (kleinere) SD-Karte zu schreiben. Der Win32DiskImager fällt hier aus, man schafft das nur in der Linux-Umgebung. Dabei gibt es zwei Möglichkeiten:

  1. Auf einem separaten Linux-PC:

    Hier ist genügend Platz auf der Festplatte und man kann sich so von der SD-Karte eine Image-Datei erzeugen. Die SD-Karte mit dem verkleinerten Dateisystem wird wider in den SD-Leser des PC gesteckt. Falls der Automounter die Karte gleich ins System eingebunden hat, kann man die beiden Partitionen wieder aushängen (umount, siehe oben). Angenommen, die Karte ist als /dev/sdc identifiziert worden, kann man mit dem Kommando dd ein Image der richtigen Größe erzeugen:

    sudo dd if=/dev/sdc conv=sync,noerror bs=512 count=15000000 of=raspiklein.img
    
    Das dauert jetzt ziemlich lang, auch weil eine Blockgröße von nur 512 Bytes gewählt wurde (das ist die Standardblockgröße, bei der Wahl einer anderen Größe muss natürlich auch der Wert von count umgerechnet werden). Im Normalfall erzeugt dd auch keinen Fortschrittsbalken, also einfach abwarten, bis die Fertig-Meldung erscheint:
    15000000+0 records in
    15000000+0 records out
    7680000000 bytes (7.3 GB) copied, 1045.21 s, 7.0 MB/s
    
    Dieses Image kann dann mittels dd oder auch unter Windows auf eine kleinere SD-Karte kopiert werden. Sie können nun die kleinere SD-Karte in den Leser stecken und mit lsblk wieder das Device ermitteln. Angenommen, er lautet /dev/sdc, läuft das Schreiben der Datei auf diese SD-Karte folgendermaßen ab (Kommandos fett):
    sudo umount /dev/sdc1
    sudo umount /dev/sdc2
    sudo dd if=raspiklein.img of=/dev/sdc conv=sync,noerror bs=512
    15000000+0 records in
    15000000+0 records out
    7680000000 bytes (7.3 GB) copied, 3590.85 s, 2.0 MB/s
    
    Achten Sie darauf, dass Sie als Ziel wirklich die SD-Karte angeben und nicht versehentlich eine andere Platte, die dann unweigerlich geschrottet würde. Das dauert jetzt wieder länger, bis die Abschlussmeldung kommt.

    Stecken Sie die neue SD-Karte in Ihren RasPi und prüfen Sie, ob er bootet und korrekt arbeitet.

  2. Auf dem Raspberry Pi:

    Wenn Sie den RasPi zum Kopieren verwenden, bleibt die SD-Karte mit dem verkleinerten Dateisystem gleich im Raspberry stecken. Es wird dann kein Zwischenimage erzeugt, sondern gleich von /dev/mmcblk0 auf die neue, kleinere Karte kopiert. Das Kommando ist fast identisch zu oben, nur dass hier keine Datei als Ziel angegeben wird, sondern die zweite SD-Karte (/dev/sdc). Gegebenenfalls müssen auch hier deren Partitionen erst ausgehängt werden (umount, siehe oben). Das Kommando lautet

    sudo dd if=/dev/mmcblk0 conv=sync,noerror bs=512 count=15000000 of=/dev/sdc
    15000000+0 records in
    15000000+0 records out
    7680000000 bytes (7.3 GB) copied, 1710.41 s, 4.2 MB/s
    
    Sie haben dann ein neues Image auf der SD-Karte. Von dieser können Sie dann unter Windows oder Linux eine Image-Datei als Backup anlegen.


Copyright © Hochschule München, FK 04, Prof. Jürgen Plate
Letzte Aktualisierung: