Im Artikel SD-Karte eines Raspberry Pi als Image klonen, sichern und zurückspielen hatte ich schon einmal beschrieben, wie man eine RasPi-Installation von der Speicherkarte sichert und zurückspielt — No Shit, Sherlock. Eine Frage tauchte dabei jedoch desöfteren auf: Die Image-Datei wird genauso groß, wie die Speicherkarte, auch wenn auf dieser noch viel Platz frei ist. Der „leere“ Platz wird quasi mit ins Image gepackt. Somit muss die neue Speicherkarte mindestens so groß sein wie die alte. Zudem belegt ein für später archiviertes Image viel Platz. Wie also kann man die Luft aus Image eines Raspberry Pi rauslassen?

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 nötige Minimum und baut in das archivierte RasPi-System zudem gleich ein Skript ein, das beim nächsten Booten des Systems auf „echter“ Hardware die Partition auf den maximalen Speicherplatz ausgedehnt. So lässt sich Image eines Raspbian-Systems von mehreren Gigabyte schnell auf ein paar hundert Megabyte verkleinern, ohne dass man viel Aufwand treiben muss. Auch beim Zurückspielen des komprimierten Systems spart man sich Arbeit, da das Dateisystem eben beim Starten des Raspberry Pi automatisch wieder auf die volle Größe ausgedehnt wird.

$ 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 simples Bash-Skript handelt, ist die Installation des Programms nicht sonderlich kompliziert: Man muss das Skript lediglich aus dem Netz herunterladen und die Rechte entsprechend setzen. Ich persönlich packe solche Skripte nach ~/bin ins Homeverzeichnis. Das System sollte diesen Ordner eigentlich automatisch in den $PATH eures Benutzers aufnehmen, sodass man das Kommando ohne Pfadangabe von überall aus im System aus aufrufen können sollte. Sollte dies bei euch nicht der Fall sein, gibt es im Netz an vielen Orten entsprechende Informationen zum Erweitern der Umgebungsvariablen (dort dreht es sich um Ubuntu, das Vorgehen ist bei anderen Distributionen jedoch nicht viel anders).

PiShrink komprimiert Raspberry Pi-Images

Nun müsstet ihr PiShrink-Skript mit der Eingabe eines beherzten pishrink.sh aus dem Terminal heraus aufrufen können. Ohne die Angabe eines Images gibt das Skript lediglich seine Syntax aus: Im Endeffekt beschränkt sich das Kommando auf die Angabe einer Image-Datei und optional eines weiteren Dateinamens eines neu zu erstellenden Images, falls PiShrink das Original-Image des Raspberry Pi unangetastet lassen soll. Belässt man es bei einem Dateiname, bearbeitet PiShrink das genannte Image.

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-System verkleinern möchte, das nicht auf einem Raspbian basiert — also beispielsweise die Kodi-Distributionen LibreELEC oder OpenELEC. Genauer gesagt muss man sagen, dass der Schalter PiShrink anweist das Ausdehnen des Systems zu unterlassen. Dazu trägt PiShrink eigentlich ein Kommando in die Datei /etc/rc.local ein, die Raspbian beim Booten automatisch ausführt. Diese Datei gibt es jedoch bei LibreELEC (und manch anderer 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 nun in den Kartenleser ein, holt sich mit lsblk die Geräte-ID und sichert dann mit dd das Image auf die Festplatte. Die Image-Datei liegt danach unter dem Namen raspberry-pi.img rund 16 GByte schwer auf der Festplatte — obwohl das Image eigentlich größtenteils leer ist. Außer dem Raspbian-System und ein paar Konfigurationen befinden sich keine 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 nun PiShrink entsprechend auf — Da es sich um ein Raspbian-System handelt, lasse ich die Option -s weg. PiShrink kopiert sodann das Image (achtet daher darauf ausreichend freien Festplattenspeicher zu haben), mountet die Kopie dann in ein temporäres Verzeichnis in /tmp und reduziert abschließend die Größe des Images von Anfangs knapp 16 GByte auf nun nur noch 1,6 GByte. Der Erfolg hängt natürlich davon ab, wie viel echte Daten auf der SD-Speicherkarte des Raspberry Pi enthalten 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 is 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 großen SD-Karte installierte Raspbian-System auf eine MicroSD mit nur 8 GByte umziehen. Dazu schreibe ich das mit PiShrink verkleinerte Image nun also wieder mit dd zurück, packe die Karte in den Raspberry Pi und starte das geschrumpfte System. Um den Speicherplatz auf die komplette Speicherkarte auszudehnen, startet das System automatisch beim ersten Bootvorgang einmal neu durch. Am Ende landet man dann wieder im gewohnten Raspbian-System, ein df -h zeigt, dass das System jetzt wieder die komplette 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 das auf eine /etc/rc.local verzichtet (wie etwa schon angesprochen die Kodi-Distributionen LibreELEC oder OpenELEC), dann bekommt ihr beim Schrumpfen des Images die folgende Fehlermeldungen. In diesem Fall müsstet ihr eben mit der Option -s verhindern, dass PiShrink das Kommando zum Vergrößern der Datenpartition in diese Datei einbaut. Dann läuft das Schrumpfen auch ohne eine Fehlermeldung durch.

### 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 aktualisierXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-
Das Dateisystem auf /dev/loop2 is nun 49976 (1k) Blöcke lang.

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

Das auf die Speicherkarte zurückgeschriebene System wird nun jedoch nicht mehr automatisch vergrößert. LibreELEC (und meines Wissens nach auch OpenELEC) bietet in seinen Menüs auch keine „Vergrößere den Speicherplatz bitte auf die maximale Partitionsgröße“-Option. Die in das System integrierte Routine ist nur für eine frisch auf die SD-Karte kopierte Installation gedacht. Mit Tools wie Gparted lässt sich die Partitionsgröße jedoch schnell wieder korrigieren, allerdings eben nur von Hand. GParted gibt es nur für Linux, Windows-Nutzer können das Programm jedoch bei Bedarf über eine Live-CD oder einen Live-USB-Stick starten

Mit Tools wie GParted lässt sich die Partitionsgröße schnell wieder anpassen.
Vorheriger ArtikelAktualisiertes Gnome-Theme für Firefox 45 und neuer
Nächster ArtikelBug-Jäger vs. Terminal-Entwickler: Aus Terminix wird Tilix
Hallo, ich bin Christoph - Linux-User, Blogger und pragmatischer Fan freier Software. Wie ihr ohne Zweifel bemerkt haben solltet, schreibe ich hier über Linux im Allgemeinen, Ubuntu im Speziellen sowie Android und andere Internet-Themen. Wenn du Freude an meinen Artikel gefunden haben solltest, dann kannst du mir über Facebook, Twitter oder natürlich dem Blog folgen.

10 Kommentare

  1. 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!

  2. 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.

  3. 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

  4. 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

  5. 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!

  6. 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…

  7. 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

  8. 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

  9. 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?

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein