Im Artikel SD-Karte eines Raspberry Pi als Image klonen, sichern und zurückspielen hatte ich bereits beschrieben, wie man eine RasPi-Installation von der Speicherkarte sichert und wiederherstellt – no shit, Sherlock. Eine Frage tauchte dabei jedoch des Öfteren auf: Die Image-Datei wird genauso groß wie die Speicherkarte, selbst wenn darauf noch viel Platz frei ist. Der „leere“ Bereich wird quasi mit ins Image gepackt. Dadurch muss die neue Speicherkarte mindestens genauso groß sein wie die alte. Zudem belegt ein für die spätere Archivierung bestimmtes Image viel Speicherplatz. Wie also lässt sich die Luft aus einem Raspberry-Pi-Image herauslassen?

Auf GitHub bin ich neulich über das Skript PiShrink gestolpert, das genau diese Aufgabe übernimmt. Das kleine Programm schnappt sich ein RasPi-Image, reduziert die Partitionsgröße auf das notwendige Minimum und integriert zudem ein Skript ins archivierte System, das beim nächsten Start auf echter Hardware die Partition automatisch auf den maximal verfügbaren Speicherplatz ausdehnt. So lässt sich das Image eines Raspbian-Systems von mehreren Gigabyte schnell auf ein paar Hundert Megabyte verkleinern – ganz ohne großen Aufwand. Auch beim Zurückspielen spart man Zeit, da sich das Dateisystem beim ersten Start des Raspberry Pi automatisch wieder auf die volle Größe erweitert.

$ mkdir ~/bin
$ wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh -P ~/bin
$ chmod +x ~/bin/pishrink.sh

Da es sich bei PiShrink um ein einfaches Bash-Skript handelt, ist die Installation des Programms nicht sonderlich kompliziert: Man muss das Skript lediglich aus dem Netz herunterladen und die Ausführungsrechte entsprechend setzen. Ich persönlich lege solche Skripte im Verzeichnis ~/bin im Home-Verzeichnis ab. Das System sollte diesen Ordner automatisch in den $PATH eures Benutzers aufnehmen, sodass man das Kommando ohne Pfadangabe von überall im System ausführen kann. Sollte das bei euch nicht der Fall sein, finden sich im Netz zahlreiche Anleitungen zum Erweitern der Umgebungsvariablen (der verlinkte Artikel bezieht sich auf Ubuntu, das Vorgehen ist bei anderen Distributionen jedoch sehr ähnlich).

PiShrink komprimiert Raspberry-Pi-Images

Nun solltet ihr das PiShrink-Skript mit einem beherzten pishrink.sh direkt im Terminal aufrufen können. Ohne die Angabe eines Images zeigt das Skript lediglich seine Syntax an. Im Wesentlichen beschränkt sich der Aufruf auf die Angabe einer Image-Datei und optional eines zweiten Dateinamens, falls PiShrink das Original-Image des Raspberry Pi unangetastet lassen soll. Gibt man nur einen Dateinamen an, bearbeitet PiShrink das genannte Image direkt.

PiShrink komprimiert Raspberry-Pi-Images

Nun solltet ihr das PiShrink-Skript mit einem beherzten pishrink.sh direkt im Terminal aufrufen können. Ohne die Angabe eines Images zeigt das Skript lediglich seine Syntax an. Im Endeffekt beschränkt sich der Aufruf auf die Angabe einer Image-Datei und optional eines zweiten Dateinamens, falls PiShrink das Original-Image des Raspberry Pi unangetastet lassen soll. Gibt man nur einen Dateinamen an, bearbeitet PiShrink das genannte Image direkt.

Raspberry Pi und Zubehör kaufen (Anzeige)
Komponente Bemerkung Preise
Raspberry Pi 4 (bis zu 8GByte) Inkl. WLAN und Bluetooth Ab ca. 40 Euro
Raspberry Pi 400 Rapberry in Tastatur integriert Ab ca. 77 Euro
Raspberry Pi Zero 2 W Inkl. Gehäuse Ab ca. 26 Euro
Gehäuse für RPi4 Diverse Modelle zur Wahl Ab ca. 7 Euro
Netzteil Ideal mit mind. 2500 mA Ab ca. 10 Euro
MicroSD-Speicherkarte Mind. 16 GByte, Class 10 Ab ca. 8,90 Euro
Micro-HDMI-Kabel CEC-fähig Ab ca. 5 Euro
Optional
Raspberry Pi-Touchscreen 7 Zoll mit 800 x 480 Pixeln Ab ca. 85 Euro
Raspberry Pi-Frame für Display Fünf verschiedene Farben Ab ca. 20 Euro
Logitech K400 Plus Touch Schnurlose Tastatur mit Touchpad Ab ca. 35 Euro
USB-WLAN-Stick 150 Mbit/s, IEEE802.11b/g/n Ab ca. 7 Euro

Der einzige Schalter -s ist dann wichtig, wenn man das Image eines RasPi-Systems verkleinern möchte, das nicht auf Raspbian basiert – also beispielsweise die Kodi-Distributionen LibreELEC oder OpenELEC. Genauer gesagt weist der Schalter PiShrink an, das automatische Ausdehnen des Systems beim nächsten Start zu unterlassen. Dazu trägt PiShrink normalerweise ein Kommando in die Datei /etc/rc.local ein, die unter Raspbian beim Booten automatisch ausgeführt wird. Diese Datei existiert jedoch bei LibreELEC (und einigen anderen Distributionen) nicht.

### Hilfe zu PiShrink aufrufen:
$ pishrink.sh
Usage: /home/toff/bin/pishrink.sh [-s] imagefile.img [newimagefile.img]
### Vorhandenes RasPi-Image verkleinern:
$ sudo pishrink.sh raspberry-pi.img
### Image verkleinern und Original behalten:
$ sudo pishrink.sh raspberry-pi.img raspberry-pi_pishrink.img
### Automatisches Vergrößern der Partition deaktivieren:
$ sudo pishrink.sh -s raspberry-pi.img raspberry-pi_klein.img

Wie kommt das nun alles zusammen? Als Beispiel verwende ich hier eine aktuelle Installation von Raspbian Lite auf einer 16 GByte großen SD-Karte. Diese legt man in den Kartenleser ein, ermittelt mit lsblk die Geräte-ID und sichert anschließend mit dd das Image auf die Festplatte. Die Image-Datei liegt danach unter dem Namen raspberry-pi.img rund 16 GByte groß auf der Festplatte – obwohl das Image eigentlich größtenteils leer ist. Außer dem Raspbian-System und ein paar Konfigurationen befinden sich keine weiteren Daten auf dem System.

$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
[...]
sdd      8:48   1  14,9G  0 disk 
├─sdd1   8:49   1    63M  0 part /run/media/[...]/boot
└─sdd2   8:50   1  14,8G  0 part /run/media/[...]/0aed834e-8c8f-412d-a276-a26
$ sudo dd if=/dev/sdd of=~/raspberry-pi.img
15894831104 Bytes (16 GB, 15 GiB) kopiert, 210 s, 75,7 MB/s     
31116288+0 Datensätze ein
31116288+0 Datensätze aus
15931539456 Bytes (16 GB, 15 GiB) kopiert, 210,459 s, 75,7 MB/s
$ ls -alh ~/raspberry-pi.img 
-rw-r--r-- 1 root root 15G 24. Feb 21:48 raspberry-pi.img

Anschließend ruft man PiShrink entsprechend auf – da es sich um ein Raspbian-System handelt, lasse ich die Option -s weg. PiShrink kopiert zunächst das Image (achtet daher darauf, dass ausreichend freier Speicherplatz vorhanden ist), mountet die Kopie in ein temporäres Verzeichnis unter /tmp und reduziert anschließend die Größe des Images: von ursprünglich knapp 16 GByte auf nur noch etwa 1,6 GByte. Der erzielte Effekt hängt natürlich davon ab, wie viele echte Daten auf der SD-Karte des Raspberry Pi gespeichert waren.

$ sudo pishrink.sh raspberry-pi.img raspberry-pi_pishrink.img
Copying raspberry-pi.img to raspberry-pi_pishrink.img...
Creating new /etc/rc.local
e2fsck 1.43.4 (31-Jan-2017)
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/loop2: 35832/959616 Dateien (0.2% nicht zusammenhängend), 321790/3872384 Blöcke
resize2fs 1.43.4 (31-Jan-2017)
resize2fs 1.43.4 (31-Jan-2017)
Die Größe des Dateisystems auf /dev/loop2 wird auf 382429 (4k) Blöcke geändert.
Start von Durchgang 2 (max = 40814)
Blöcke werden verschoben     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start von Durchgang 3 (max = 119)
Die Inode-Tabelle wird gelesenXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start von Durchgang 4 (max = 3178)
Die Inode-Referenzen werden aktualisierXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-
Das Dateisystem auf /dev/loop2 ist nun 382429 (4k) Blöcke lang.

Shrunk raspberry-pi_pishrink.img from 15G to 1,6G
$ ls -alh raspberry-pi*
-rw-r--r-- 1 root root  15G 27. Feb 11:08 raspberry-pi.img
-rw-r--r-- 1 root root 1,6G 27. Feb 11:30 raspberry-pi_pishrink.img

Geschrumpftes RasPi-Image wiederherstellen

Zum Test soll das ursprünglich auf einer 16-GByte-SD-Karte installierte Raspbian-System auf eine MicroSD-Karte mit nur 8 GByte umziehen. Dazu schreibe ich das mit PiShrink verkleinerte Image wieder mit dd auf die neue Karte, setze sie in den Raspberry Pi ein und starte das geschrumpfte System. Um den verfügbaren Speicherplatz vollständig zu nutzen, führt das System beim ersten Bootvorgang automatisch einen Neustart durch. Anschließend landet man im gewohnten Raspbian-System – ein df -h zeigt, dass das System jetzt die gesamte SD-Karte verwendet.

$ lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
[...]
sdd      8:48   1   7,4G  0 disk 
├─sdd1   8:49   1    63M  0 part /run/media/[...]/boot
└─sdd2   8:50   1   7,3G  0 part /run/media/[...]/0aed834e-8c8f-412d-a276-a26
$ sudo dd if=raspberry-pi_pishrink.img of=/dev/sdd bs=1M; sync
1560+1 Datensätze ein
1560+1 Datensätze aus
1636684288 Bytes (1,6 GB, 1,5 GiB) kopiert, 116,203 s, 14,1 MB/s
pi@raspberrypi:~ $ df -h
Dateisystem    Größe Benutzt Verf. Verw% Eingehängt auf
/dev/root       7,2G    990M  6,0G   14% /
devtmpfs        459M       0  459M    0% /dev
tmpfs           463M       0  463M    0% /dev/shm
tmpfs           463M    6,2M  457M    2% /run
tmpfs           5,0M    4,0K  5,0M    1% /run/lock
tmpfs           463M       0  463M    0% /sys/fs/cgroup
/dev/mmcblk0p1   63M     21M   42M   33% /boot
PiShrink reduziert das Image eines Raspberry-Pi-Systems auf die minimale Größe.

Sichert man ein Raspberry-Pi-System, das nicht auf Raspbian basiert und keine /etc/rc.local enthält – wie etwa die bereits erwähnten Kodi-Distributionen LibreELEC oder OpenELEC – erscheinen beim Schrumpfen mit PiShrink Fehlermeldungen. Der Grund: PiShrink versucht standardmäßig, ein Kommando zur späteren automatischen Vergrößerung der Partition in diese Datei einzutragen. Um das zu vermeiden, muss beim Aufruf die Option -s verwendet werden. Damit lässt sich das Image auch ohne rc.local erfolgreich verkleinern.

### Fehlermeldungen beim Schrumpfen eines LibreELEC-Images:
$ sudo pishrink.sh libreelec.img
[...]
md5sum: /tmp/tmp.4ornQ3Va4y/etc/rc.local: Datei oder Verzeichnis nicht gefunden
/home/[...]/bin/pishrink.sh: Zeile 63: [: !=: Einstelliger (unärer) Operator erwartet.
[...]
### LibreELEC, OpenELEC und Co. schrumpft man besser so:
$ sudo pishrink.sh -s libreelec.img
Skipping autoexpanding process...
e2fsck 1.43.4 (31-Jan-2017)
/dev/loop2: Journal wird wiederhergestellt
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/loop2: 861/1810432 Dateien (1.0% nicht zusammenhängend), 252448/7235584 Blöcke
resize2fs 1.43.4 (31-Jan-2017)
resize2fs 1.43.4 (31-Jan-2017)
Die Größe des Dateisystems auf /dev/loop2 wird auf 49976 (1k) Blöcke geändert.
Start von Durchgang 2 (max = 15759)
Blöcke werden verschoben     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start von Durchgang 3 (max = 884)
Die Inode-Tabelle wird gelesenXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start von Durchgang 4 (max = 143)
Die Inode-Referenzen werden aktualisiertXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-
Das Dateisystem auf /dev/loop2 ist nun 49976 (1k) Blöcke lang.

Shrunk libreelec.img from 7,5G to 563M

Das zurückgeschriebene System vergrößert sich anschließend jedoch nicht automatisch, da LibreELEC (und nach aktuellem Kenntnisstand auch OpenELEC) in seinen Menüs keine Option bietet, die Datenpartition manuell auf die volle Kartengröße auszudehnen. Die interne Routine zur Größenanpassung greift nur bei einer frisch kopierten Erstinstallation, wie im Skript ersichtlich. Um die Partition dennoch vollständig zu nutzen, hilft nur manuelles Nacharbeiten mit einem Partitionswerkzeug wie GParted. Unter Linux ist GParted direkt verfügbar, Windows-Nutzer können das Tool über eine Live-CD oder einen Live-USB-Stick verwenden.

Mit Tools wie GParted lässt sich die Partitionsgröße schnell wieder anpassen.
guest
11 Kommentare
Inline Feedbacks
Zeige alle Kommentare
Anonym

Genial, genau das, was ich lange Zeit gesucht habe.

Nach voller Einrichtung meines OMV-Nas-Servers auf dem Raspberry will ich das Image sichern und später auch auf einer 8Gb-Karte (damals hatte ich nur eine 16er zur Hand) notfalls wiederherstellen können.

Vielen Dank!

Sergej

Danke für den Artikel. Hab diese Seite zufällig gefunden und bin froh darüber. Man erfährt hier immer wieder mal Interessante und nützliche Sachen.

Marek

Hallo Christoph, seit Jahren schaue ich in unregelmäßigen Abständen auf deiner Seite vorbei. Nahezu jedes Mal entdecke ich in deinen dann zurückliegenden veröffentlichten Einträgen Neues und Interessantes für mich. Vielen Dank, dass du pishrink entdeckt und uns an dieser Entdeckung hast teilnehmen lassen!! Das Skript ist gerade dabei ein Raspi-Image von einer 16 GB micro SDHC-Karte zu verkleinern. Grüße, M.

Link: http://www.forum-raspberrypi.de/Thread-raspbian-image-verkleinern-mit-pishrink

Norbert

Hi Christoph,
SUPER!! Genau das, was ich brauchte.
Habe in meinem RasPi 3B eine 32-GB-Karte und es ist extrem lästig, wenn die Backups so viel Platz einnehmen.
ABER:
Obwohl ich ein orginal Raspbian einsetze, funktioniert die automatische Expansion nach dem Restore & Boot mit der neuen SD nicht!
Mache ich was falsch, oder geht das beim RasPi 3B nicht?

Ist allerdings auch kein Beinbruch, da im raspi-config die Möglichkeit besteht, das Dateisystem zu expandieren.
Danach ist wieder die gesamte SD nutzbar.

Grüße
Norbert aus Berlin

Nils

Achtung, scheint explizit nicht für NOOB-Raspian zu funktionieren! Kurze Info wäre für mich hilfreich gewesen…

Trotzdem Danke für die tollen Fundstücke!

Kev

Hi,
ich komme leider nicht weiter. Habe ubuntu auf VM laufen.

$ sudo ./pishrink.sh pibackup.img

Creating new /etc/rc.local
/dev/loop0: Inodes that were part of a corrupted orphan linked list found.

/dev/loop0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
(i.e., without -a or -p options)
resize2fs 1.42.13 (17-May-2015)
Please run ‚e2fsck -f /dev/loop0‘ first.

./pishrink.sh: line 148: 7779968 – : syntax error: operand expected (error token is „- „)
resize2fs 1.42.13 (17-May-2015)
Please run ‚e2fsck -f /dev/loop0‘ first.

ERROR: resize2fs failed…

Karl

Hallo Christoph,
Expansion nach dem Raspbian Restore & Boot mit der neuen SD geht definitiv nicht!
Ich habe es nun mehrfach probiert. Gibt es hier weitere Informationen von Deiner Seite?
Danke

Michael

Beim Versuch eine PI-Installation auf einer 32 GB SD Karte (Quelle) auf eine 16 GB Karte zu kopieren kann ich das Image von der Quelle mit dd erzeugen, bekomme aber die Fehlermeldung
Fehler: Es können keine überlappenden Partitionen existieren.

was mache ich falsch?

sudo dd if=/dev/sdb of=/mnt/share/sdb.img

lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 12G 0 disk
└─sda1 8:1 0 12G 0 part /
sdb 8:16 1 29,7G 0 disk
├─sdb1 8:17 1 1,4G 0 part
├─sdb2 8:18 1 1K 0 part
├─sdb5 8:21 1 32M 0 part /media/michael/SETTINGS
├─sdb6 8:22 1 66M 0 part /media/michael/boot
└─sdb7 8:23 1 28,2G 0 part /media/michael/root
sr0 11:0 1 1,4G 0 rom /media/michael/Ubuntu 17.10 amd64

sudo fdisk -l sdb.img
Medium sdb.img: 29,7 GiB, 31914983424 Bytes, 62333952 Sektoren
Einheiten: sectors von 1 * 512 = 512 Bytes
Sektorengröße (logisch/physisch): 512 Bytes / 512 Bytes
I/O Größe (minimal/optimal): 512 Bytes / 512 Bytes
Typ der Medienbezeichnung: dos
Medienkennung: 0x000baf66

Gerät Boot Start Ende Sektoren Größe Id Typ
sdb.img1 8192 2994140 2985949 1,4G e W95 FAT16 (LBA)
sdb.img2 2994141 62333951 59339811 28,3G 5 Erweiterte
sdb.img5 2998272 3063805 65534 32M 83 Linux
sdb.img6 3063808 3198975 135168 66M c W95 FAT32 (LBA)
sdb.img7 3203072 62333951 59130880 28,2G 83 Linux

pishrink-Aufruf
sudo /home/michael/bin/pishrink.sh /mnt/share/sdb.img /mnt/share/sdb_klein.img

sudo /home/michael/bin/pishrink.sh /mnt/share/sdb.img /mnt/share/sdb_klein.img
[sudo] Passwort für michael:
Copying /mnt/share/sdb.img to /mnt/share/sdb_klein.img…
Creating new /etc/rc.local
root: 145429/1851392 Dateien (0.2% nicht zusammenhängend), 1322279/7391360 Blöcke
resize2fs 1.43.5 (04-Aug-2017)
resize2fs 1.43.5 (04-Aug-2017)
Die Größe des Dateisystems auf /dev/loop0 wird auf 1693646 (4k) Blöcke geändert.
Start von Durchgang 2 (max = 506911)
Blöcke werden verschoben XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start von Durchgang 3 (max = 226)
Die Inode-Tabelle wird gelesenXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Start von Durchgang 4 (max = 12835)
Die Inode-Referenzen werden aktualisiertXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Das Dateisystem auf /dev/loop0 is nun 1693646 (4k) Blöcke lang.

Fehler: Es können keine überlappenden Partitionen existieren.
Shrunk /mnt/share/sdb_klein.img from 30G to 1,6G

mehlanmich@gmx. net

Gibt es inzwischen eine Version von pishrink, die mit NOOBS-Partitionen zurecht kommt oder evtl. ein anderes Tool, mit dem man die SD Karten-Images für die Übertragung auf eine kleine Karte anpassen kann?

Solderdot

Danke für den Artikel Tolle Sache.
Funktioniert aber nicht ganz so gut wie erwartet: 64GB SD-Karte zu 30% benutzt. Das Image, das PiShrink erzeugt, passt aber dennoch nicht auf eine 32GB SD-Karte. Ich hätte gedacht, dass das locker passen sollte…