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
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
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!
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.
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
Hi Marek, gerne doch 🙂
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
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!
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…
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
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
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?
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…