Problematik / Technische Grundlage:
Ein vollständiges Abbild (clone) einer SD zu erstellen ist der einfachste und schnellste Weg ein Backup bzw eine Sicherung seines Systems zu erzeugen.
Problem dabei ist allerdings das über dd oder Win32DiskImager usw man ein vollständiges 1:1 Abbild erstellt, es werden also auch leere Sektoren gesichert - ist die SD 16GB ist auch das Image 16GB.
Wenn die Quell-SD zB 16300 MB groß ist aber die Ziel-SD nur 16200 dann passt das Image nicht auf eine andere 16GB SD Karte oder sogar auf eine kleinere, obwohl nur zB 4GB Speicher tatsächlich belegt sind...
Es gibt fast immer minimale Unterschiede, auch wenn auf der SD Karte die selbe Größe (zB 16GB) aufgedruckt ist. Manche Hersteller rechnen mit den korrekten 1024, andere wiederum aber nur mit 1000 -> 16 x 1024 ergibt 16384 aber 16 x 1000 ergibt eben nur 16000 (MB). Aber auch der Herstellungsprozess kann minimale Unterschiede hervorrufen.
Verschiedene Backupmethoden stehen zur Verfügung:
1) dd Backup der ganzen SD Karte
2) tar Backup eines beliebigen Verzeichnisses, wobei bei / als Verzeichnis die gesamte Pi gesichert wird
3) xbmc Backup, welches das xbmc Konfigurationsverzeichnis in einem tar sichert
4) rsync Backup, wobei Hardlinks benutzt werden um die Datenmenge in den Backupversionen zu reduzieren.
dd: Vollbackup: ja , Backupzeit: lange , Backupgröße: gross , Datenkompression: nein , CPU belastet: mittel , Karte belastet: hoch , Selektiver Restore möglich: nein , Dateisystem: alles
tar: Vollbackup: nein , Backupzeit: mittel , Backupgröße: mittel , Datenkompression: ja , CPU belastet: mittel , Karte belastet: mittel , Selektiver Restore möglich: ja , Dateisystem: alles
xbmc: Vollbackup: nein , Backupzeit: kurz , Backupgröße: klein , Datenkompression: ja , CPU belastet: nein , Karte belastet: kaum , Selektiver Restore möglich: ja , Dateisystem: alles
rsync: Vollbackup: nein , Backupzeit: kurz , Backupgröße: mittel , Datenkompression: nein , CPU belastet: nein , Karte belastet: kaum , Selektiver Restore möglich: ja , Dateisystem: ext2/ext3
(Quelle der Tabelle)
Ich möchte euch hier beschreiben wie die Profis (ich bin aber keiner ) dies handhaben - ihr habt das vielleicht schon mal gesehen das ein Raspbian Image o.ä. nur 200MB groß ist aber nachdem ihr es auf die SD geflasht habt ist die Partition 2GB ... Die Profis löschen/entfernen die leeren Sektoren um das Image nur auf die Größe des belegten Speicherplatzes zu reduzieren - bzw der freie Speicher wird mit 0'n beschrieben, erstellen anschließend das Image und lässt sich dadurch kleiner packen (oder mounten ein Image und 0'n den leeren Speicher)
Zum erstellen eines Images ist der einfachste Weg einen größeren USB-Stick oder eine USB-Festplatte an den PI anzuschließen und darauf das Image zu schreiben. Ihr solltet aber darauf achten dass das Laufwerk nicht allzu langsam ist, sonst dauert es ziemlich lange (billige USB-Sticks haben nur eine Schreibgeschwindkeit von umdie 2MB/s, ist die SD 16GB groß kann es bis zu 2 Stunden dauern..)
Achtet auch darauf das FAT32 nur eine maximale Dateigröße von 4 GB unterstützt. Ihr solltet also entweder ein Linux Dateisystem oder NTFS verwenden.
Ich hab hierfür eine SSD verwendet da damit der maximale USB-Datendurchsatz des PIs ausgenutzt werden kann: ca. 30MB/s
(ich nutze also den PI um von ihm direkt ein Image zu erstellen)
Eine weitere Möglichkeit besteht aber auch darin die SD an ein anderes Linux System anzuschließen bzw zu mounten - das kann auch ein Virtuelles über zB VirtualBox oder eine andere VM sein.
Wenn ihr das Backup Live vom/über den RaspberryPI erstellen wollt ist es wichtig vorher das System als read-only zu mounten! Denn es kann zu Probleme kommen wenn gerade auf die Partition geschrieben wird wärend ihr ein Image davon erzeugt - in solch einem Fall sichert ihr nur Datenschrott
Dies erreicht ihr über /etc/fstab . Mehr Details dazu weiter unten!
Oder man beendet vorher alle Dienste und Programme, also zB: service apache2 stop ; service mysql stop ;service cron stop und natürlich auch eure selber erstellen Scripts oder gar RaspBMC usw!
Falls euer Sicherungslaufwerk (wohin das Image geschrieben wird) mit NTFS formatiert ist müsst ihr auch noch folgendes beachten:
Benötigtes Paket installieren:
Wenn ihr das Sicherungslaufwerk über Linux formatieren wollt könnt ihr nun folgenden Befehl nutzen:
(quick format)
Durch NTFS wird aber die Schreibgeschwindigkeit unter Linux stark reduziert! Besser wäre den Datenträger mit ext3 oder ext4 zu formatieren:
Anleitung:
Ihr geht dabei wie folgt vor:
(alle Befehle erfordern root Rechte, also ggf sudo davor schreiben!)
Zunächst müssen wir erst das RaspberryPI System als read-only mounten damit nicht wärend des sicherns auf die Partitionen geschrieben wird (zB von Diensten wie CRON o.ä.) und unsere Sicherung dadurch nutzlos werden würde (siehe dicker roter Hinweis weiter oben).
Dazu müsst ihr /etc/fstab bearbeiten und "ro" zu den beiden Partitionen hinzufügen, sodass es ungefähr wie folgt aussieht:
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults,ro 0 2
/dev/mmcblk0p2 / ext4 defaults,noatime,ro 0 1
Diese Änderung müsst ihr nach dem erstellen es Abbilds wieder rückgängig machen - und zwar müsst ihr dazu folgenden Befehl ausführen bevor ihr logischerweise /etc/fstab verändern bzw speichern könnt:
Und dann rebooten damit die Partitionen der SD beim nächsten Systemstart nur als read-only gemounted wird:
Nach dem reboot könnt ihr das ganze prüfen indem ihr über den Befehl mount kontrolliert ob " (ro " hinter der " / " und " /boot " Partition steht - oder ihr versucht jeweils in " / " und " /boot/ " eine Datei zu erzeuchen was aber nicht funktionieren dürfte -> touch /test ; touch /boot/test
Herausfinden ob das SicherungsLaufwerk erkannt wurde:
(die erste Partition ist meistens sda1 oder sdc1)
Verzeichnis erstellen wohin wir das Laufwerk mounten und die erste Partition mounten/einbinden:
(Pfade ggf anpassen)
Der reguläre Weg ein vollständiges 1:1 Abbild der SD zu erstellen sähe normalerweise wie folgt aus:
(if -> input file , of -> output file)
Das erzeugt aber besagtes 1:1 Abbild, also in meinem Fall wäre das rpi.img dann ca. 8GB groß.
Funktioniert so natürlich auch, ist aber wie ich finde unschön, vorallem wenn man die Datei ggf auch zum Download bereitstellen möchte
Nun gibt es ein paar Tricks.
Der erste Trick besteht darin beim erstellen des Abbilds die Ausgabe an gzip zu leiten (pipe (|)) um das Abbild komprimieren zu lassen. Mit folgendem Befehl spart man sich einen Zwischenschritt - man kann das komprimieren aber auch nach dem erstellen durchführen.
Das spart schon mal einiges an Platz denn ungepackt wäre das Image ~7,6GB gross:
Zur Wiederherstellung sähe der Befehl so aus:
Jenachdem wie groß eure SD Karte ist kann das erstellen ziemlich lange dauern - in meinem Fall hat es mit NTFS 45 Minuten gedauert:
root@raspberrypi:~# dd if=/dev/mmcblk0 of=/mnt/sda1/rpi.img bs=1M
7695+0 Datensätze ein
7695+0 Datensätze aus
8068792320 Bytes (8,1 GB) kopiert, 2712,63 s, 3,0 MB/s
root@raspberrypi:~#
Mit ext4 war es dahingegen mit nur ca 10 Minuten merklich schneller:
root@raspberrypi:~# date ; dd if=/dev/mmcblk0 of=/mnt/sda1/rpi.img bs=1M ; date
Do 3. Jul 18:44:59 CEST 2014
7695+0 Datensätze ein
7695+0 Datensätze aus
8068792320 Bytes (8,1 GB) kopiert, 711,419 s, 11,3 MB/s
Do 3. Jul 18:56:51 CEST 2014
root@raspberrypi:~#
Problematisch hierbei ist allerdings das Windows nicht von alleine auf Linux-Dateisysteme zugreifen kann. Dafür müßte man einen extra Treiber installieren zum Beispiel > diesen <.
Die Größe des Abbilds können wir nun mit folgendem Befehl kontrollieren:
Bevor ihr das Sicherungslaufwerk umount'et (vor dem abziehen wieder aushängen) solltet ihr aber unbedingt den Befehl sync ausführen damit der Buffer geleert und alle Daten geschrieben werden. Anschließend müsst ihr auch vor dem Abziehen das Laufwerk wie gesagt umount'en:
Nun aber zum Hauptmerkmal dieser Anleitung:
Hier gibt es nun mehrere Möglichkeiten:
- Das erzeugte Image mounten, den freien Speicher mit nullen voll schreiben indem man eine Datei erzeugt und diese Datei anschließend wieder löschen. Wenn man das Image dann mit zip o.ä. packt wird es wesentlich kleiner als wenn man diesen Schritt nicht machen würde.
Hierbei muss man darauf achten dass das erstellte Abbild mehrere Partitionen beinhaltet, man also jede Partition einzeln mounten muss! Wie das detailliert geht hab ich bereits letztes Jahr in einer anderen Anleitung beschrieben. Bitte lest euch dort ein wie das genau geht. Wenn ihr Raspbian verwendet sollten die offset Werte aber bei allen gleich sein.Codemkdir -p {/mnt/rpi1,/mnt/rpi2} mount /mnt/sda1/rpi.img /mnt/rpi1 -o offset=$((8192*512)) mount /mnt/sda1/rpi.img /mnt/rpi2 -o offset=$((122880*512))
Damit haben wir jetzt vom Image die /boot/ Partition nach /mnt/rpi1/ und die root-Partition nach /mnt/rpi2/ gemountet.
Jetzt schreiben wir in beide Partitionen eine Datei mit nullen und anschließend löschen wir diese wieder. Danach können wir die mounts wieder entfernen:Codecat /dev/zero > /mnt/rpi1/big_zero ; sync; rm /mnt/rpi1/big_zero cat /dev/zero > /mnt/rpi2/big_zero ; sync; rm /mnt/rpi2/big_zero umount /mnt/rpi*
Das da jeweils eine Fehlermeldung von wegen "kein Speicherplatz mehr verfügbar" kommt ist normal und Absicht
Die Image Größe hat sich nun noch nicht verändert - wenn man die Datei aber nun pakt wird sie kleiner als es vorher möglich war. - Es gibt eine ganze Reihe Programme die sowas ähnliches wie die 1.Möglichkeit beschreibt, machen. Dazu gehört zum Beispiel fsarchiver , btrfs , zerofree , sfill , e2image oder partimage. Letzteres unterstützt leider kein ext4 und man kann ext4 leider nicht so einfach in ext3 umwandeln bzw ist das nicht zu empfehlen..
- Es gibt auch einen manuellen Weg die zweite Partition (root-Partition) zu shrink'en. Dieser Weg ist etwas aufwendiger und auch etwas gefährlich sofern man etwas falsch macht - erreicht aber dass das *.img auch ohne es zu packen kleiner wird
Wie bei der 1.Methode benötigen wir die offset Werte, allerdings mounten wir die 2.Partition nicht sondern erzeugen dafür nur ein extra Device auf das wir dann zugreifen können:
Dieser Befehl sollte euch dann dev/loop0 o.ä. ausgegeben haben, das ist das neue Devive welches wir in den nächsten Schritten ansprechen.
Nun überprüfen wir das Device erst mal auf Fehler:Das sollte fehlerfrei verlaufen, ansonsten habt ihr ein Problem...
Nun müssen wir erst mal herausfinden wieviel Speicherplatz auf dem Device belegt ist, damit wir wissen auf welche Größe wir die Partition shrink'en können. Dazu mounten wir das Device temporär nach /mnt/rpi1, prüfen den Benutzten Platz und umounten es für die späteren Schritte wieder:
Die Ausgabe von df -h sieht bei mir folgendermassen aus:(hab die Ausgabe aufs nötigste gekürzt)
Das zeigt also das ca. 2,3GB belegt sind (ich hab da schon einiges installiert, deshalb ist bei mir mehr belegt als es bei euch sein könnte). Es kann also nicht schaden das Device (bzw die Partition) auf 3GB zu verkleinern - und genau das machen wir jetzt:
Anschließend können wir durch mounten des Devices noch mal kontrollieren ob die Größe nun weniger ist als zuvor (es würden nun 2,9G anzeigen werden), danach ist aber wichtig das angelegte Device für die nächsten Schritte wieder zu löschen (Daten bleiben erhalten, wir entfernen nur das selbst erzeugte loop device):
Das von uns modifizierte Image ist jetzt aber leider noch nicht kleiner als vorher. Darum kümmern wir uns nun - und jetzt wird es leider auch etwas komplizierter...In den folgenden Schritten müssen wir nun ein blanko Image mit den selben Spezifikation erzeugen wie das normale Image, Partitionen erzeugen und die Daten kopieren.
Erstmal fragen wir die Spezifikationen unseres Images ab:Die Ausgabe sieht bei mir so aus:
Code
Alles anzeigenDisk /mnt/sda1/rpi.img: 8068 MB, 8068792320 bytes 255 heads, 63 sectors/track, 980 cylinders, total 15759360 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: 0x000981cb Device Boot Start End Blocks Id System /mnt/sda1/rpi.img1 8192 122879 57344 c W95 FAT32 (LBA) /mnt/sda1/rpi.img2 122880 15759359 7818240 83 Linux
Für uns sind die ersten 3 Zeilen wichtig: 255 heads, 63 sectors -> 255 x 63 = 16065 x 512bytes = 8225280 bytes pro cylinder.
Wir erstellen ein Image mit 4MB am Anfang (für den MBR) + 56MB (FAT32 Partition, für /boot/) + 3GB System Partition (3072MB) ; ergibt also eine Gesamtgröße von 3.132 MBytes oder 3.284.140.032 Bytes (1 kB = 1024 Bytes). Letztere Zahl teilen wir durch 'bytes pro cylinder' und erhalten den cylinder Wert zum erstellen des blanko Images: 3284140032 / 8225280 = 399,27 cylinders. Nachkomma Stellen sind blöd also runden wir auf 400 auf!
Blanko-Image erzeugen:Coderoot@raspberrypi:~# dd if=/dev/zero of=/mnt/sda1/3GB.img bs=8225280c count=400 400+0 Datensätze ein 400+0 Datensätze aus 3290112000 Bytes (3,3 GB) kopiert, 124,484 s, 26,4 MB/s root@raspberrypi:~#
Jetzt benutzen wir fdisk um direkt die korrekte Struktur im Image zu erzeugen und legen darüber auch gleich die Partitionen an:
Wir legen die ersten Partition (/boot) an und ändern den Type auf W95 FAT32 (LBA):Code
Alles anzeigenCommand (m for help): n Partition type: p primary (0 primary, 0 extended, 4 free) e extended Select (default p): p Partition number (1-4, default 1): Using default value 1 First sector (2048-6425999, default 2048): 8192 Last sector, +sectors or +size{K,M,G} (8192-6425999, default 6425999): +56M Command (m for help): t Selected partition 1 Hex code (type L to list codes): c Changed system type of partition 1 to c (W95 FAT32 (LBA))
Jetzt legen wir in der selben fdisk-Session die zweite (System)Partition an und ändern den Type auf Linux:Code
Alles anzeigenCommand (m for help): n Partition type: p primary (1 primary, 0 extended, 3 free) e extended Select (default p): p Partition number (1-4, default 2): Using default value 2 First sector (2048-6425999, default 2048): 122880 Last sector, +sectors or +size{K,M,G} (122880-6425999, default 6425999): +3072M Command (m for help): t Partition number (1-4): 2 Hex code (type L to list codes): 83
Nun das gemachte kontrollieren:Code
Alles anzeigenCommand (m for help): p Disk /mnt/sda1/3GB.img: 3290 MB, 3290112000 bytes 255 heads, 63 sectors/track, 400 cylinders, total 6426000 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: 0xd2c1a4b8 Device Boot Start End Blocks Id System /mnt/sda1/3GB.img1 8192 122879 57344 c W95 FAT32 (LBA) /mnt/sda1/3GB.img2 122880 6414335 3145728 83 Linux
Anschließend müssen wir die gemachten Änderungen schreiben/speichern und fdisk beenden:Code
Alles anzeigenCommand (m for help): w The partition table has been altered! WARNING: If you have created or modified any DOS 6.x partitions, please see the fdisk manual page for additional information. Syncing disks. root@raspberrypi:~#
Soweit so gut... Jetzt 'kopieren' wir die erste Partition von unserem Backup-Image zum Blanko-Image, überspringen (skip) aber die ersten 4MB (8192 sectors of 512 bytes) und suchen (seek) weitere 4MB (8192 sectors of 512 bytes) um 56MB zu kopieren (114688 sectors of 512 bytes):
Das gleiche Spiel machen wir jetzt auch für die 2.Partition: wir überspringen 4 MBytes + 56 MBytes (122880 sectors of 512 bytes, 60 MBytes) vom input file und seeking 4 MBytes + 56 MBytes (122880 sectors of 512 bytes, 60 MBytes) im output file um 3072 MBytes (6291456 sectors of 512 bytes) zu kopieren..:
...fertig...
Das neu erstellte Image ist jetzt 3GB groß und beinhaltet alle Daten vom Backup-Image.
(quelle)
Weitere Hinweise:
Ein Nachteil von dd ist die Geschwindigkeit, weil es wirklich über den kompletten Speicher geht. Sobald ich mal wieder etwas Zeit hab werd ich (oder andere?) das Tutorial um weitere Linux-Sicherungsprogramme erweitern
Weitere, ähnliche Tutorials in diesem Forum sind folgende:
Backup einer SD-Karte
Automatisches Erstellen eines Backups (Pi sichert sich selbst)
Backup des laufenden Systems anlegen