Samstag, 11. Oktober 2014

Backup Raspberry SD Card im laufenden Betrieb

Heute habe ich mich mit dem Backup vom Raspberry beschäftigt. Hier gibt es verschiedene Ansätze:
  1. Backup der geänderten Konfigurationsdateien und der "Projektdaten"
    + schnell da es sich zumeist um wenige Daten und Dateien handelt
    + Backup kann auch in ein Backup Verzeichnis auf der SD Karte geschehen
    - es müssen alle geänderten Dateien gefunden werden
    - beim zurückspielen muss sichergestellt werden, dass alle Pakete und Module installiert sind
  2. Vollständige Kopie der gesamten SD Karte
    + einfacher Klon der SD Karte ohne große Aufwände
    + zurückspielen auf neue SD Karte recht problemlos möglich
    - sehr großer Speicherbedarf
    - kein inkrementelles Backup
Noch einen Hinweis im Vorfeld. In den allerwenigsten Fällen wird der gesamte Speicherplatz auf der SD Karte verwendet. Ich habe mir deswegen ein "Master Image" erstellt, in welchen schon alle notwendigen Informationen für mein Lan liegen und welches auf eine 4GB Karte passt. Die exakte Größe der SD Karte variiert von Karte zu Karte -selbst im selben Image. Ich habe deswegen maximal 3,9 GB als Imagedatei

Okay los geht ich habe mich für die zweite Methode entschieden und schreibe die Daten über das Netzwerk auf einen anderen PC. Dies kann sowohl auf die Freigabe eines Linux oder eines Windows Systems geschehen.

Für Windowsziele

Hier sind auf dem Raspberry einige zusätzliche Pakete notwendig. Diese werden mit folgenden Befehl installiert:

sudo apt-get install samba-client samba-common cifs-utils

Es wird ein Verzeichnis erstellt, welche dann auf das Netzlaufwerk des WindowsPCs gemountet wird.

sudo mkdir /WindowsVerzeichnis

Danach wird die Windowsfreigabe auf dieses Verzeichnis gemounted:

sudo mount -t cifs -o guest //WindowsPC/Freigabe /WindowsVerzeichnis

Dabei sollte darauf geachtet werden das die Windowsfreigabe keine Leerzeichen enthält. Ist dies der Fall muss die Freigabe in Anführungszeichen  geschrieben werden.

Für Linuxziele

Hier verwenden wir NFS. Normalerweise sollten die Clientpakete auf dem Raspberry sein. Last uns zu Sicherheit noch mal nachschauen:

sudo apt-get install nfs-common

Ich gehe mal davon aus das die Freigabe auf dem Ziel eingerichtet ist. Auf dem Raspberry erstellen wir ein Verzeichnis auf welches die NFS Freigabe gemountet wird:

sudo mkdir /LinuxVerzeichnis

Danach wird die Freigabe gemountet. Dazu wird der folgende Befehl verwendet:


sudo mount 192.168.76.110:/share /LinuxVerzeichnis

Okay es geht gemeinsam weiter

Anschließend kann ich nachprüfen ob alles funktioniert. Der Befehl

df -h

 solle in der Rückgabe auf das gemountete Verzeichnis verweisen:

//WindowsPC/Freigabe 2.0G 1.8G 200M 10% /WindowsVerzeichnis
//192.168.76.110:/share  2.0G 1.8G 200M 10% /LinuxVerzeichnis

Wir gehen in das Verzeichnis und schauen ob wir die Berechtigung zum Schreiben von Daten haben. Der einfachste Weg ist:

cd /Linux/Verzeichnis
touch test.txt
ls

Gibt touch keine Fehlermeldung und ls zeigt die Datei, dann kann man noch mal auf dem Zielsystem schauen ob die Datei auch dort zu sehen ist.... aber das ist dann schon eher unnötig.
Okay wir suchen uns jetzt die Bezeichnung der SD Karte:

fdisk -l

gibt bei meiner 16GB Karte folgende Ausgabe:

Disk /dev/mmcblk0: 16.1 GB, 16130244608 bytes
4 heads, 16 sectors/track, 492256 cylinders, total 31504384 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
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880     7403519     3640320   83  Linux

Die Bezeichnung, die wir suchen ist /dev/mmcblk0. Ebenfalls kann man hier sehen das auf der Karte zwei Paritionen sind. Die FAT32 parition wird verwendet um zu Booten. In der Linuxpartition sind alle Daten des Raspberry.

Die Größe der beiden Partitionen lässt sich von den Blöcken berechnen:
Die Bootpartition (FAT32) geht von Block 8192 bis Block 122879. Somit ist die Partition 122879-8192 Blöcke groß. Bei einer Blockgröße von 512bytes ergibt dies ca 59MB.

Die Datenpartition ist schon größer. Mit der Selben Formel Endblock - Startblock (7403519 - 122880) ergibt die Anzahl von 7280639 Blöcken. Das macht bei 512byte pro Block ca 3728 MB.

Zusammen belegen unsere beiden Partitionen 3,8GB auf der 16,1GB großen Karte. Im Vollbackup werden die gesamten 16GB über das Netzwerk geschoben. Da wir uns in einem Privaten Netz befinden und der Raspberry hoffentlich über LAN läuft ist das so erst mal ok. Nach dem Klonen der SD Karte werfen wir den ungenutzten Platz aus dem Klon wieder raus. Aber....wollen wir erst mal anfangen. Wir kopieren mit dd den gesamte Inhalt von mmcblk0 auf das Netzwerkshare:


sudo dd if=/dev/mmcblk0 of=/LinuxVerzeichnis/sdKarte.img bs=1M

Der Raspberry ist dann erst mal ganz gut am Knechten. Bei mir macht der das immer richtig gemütlich aber nach einer weile kommt:


sdKarte.img bs=1M
15383+0 records in
15383+0 records out
16130244608 bytes (16 GB) copied, 3221.12 s, 5.0 MB/s

Wie erwartet sind auf dem Zielverzeichnis jetzt 16GB in der Datei sdKarte.img. Mit dem  Befehl


ls -l

bekommen wir das erwartete Ergebnis:

-rw-r--r-- 1 4294967294 4294967294 16130244608 Oct 11 23:48  sdKarte.img

Wir wissen, dass davon nur 3,8GB verwendet werden. Deswegen lassen wir die Luft aus dem Image.


Dazu prüfen wir noch einmal die Blöcke in dem Image.

sudo fdisk -l /LinuxVerzeichnis/sdKarte.img

liefert ein ähnliches Ergebnis, wie wir es schon zuvor auf der SD Karte selbst gesehen haben:

Disk sdKarte.img: 16.1 GB, 16130244608 bytes
255 heads, 63 sectors/track, 1961 cylinders, total 31504384 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
sdKarte.img1            8192      122879       57344    c  W95 FAT32 (LBA)
sdKarte.img2          122880     7403519     3640320   83  Linux

Das ist gut! Jetzt truncaten wir die Datei bei auf die verwendete Größe. Diese wird in dem Befehl mit der Anzahl der Sektoren * Blockgröße berechnet. Dabei darf nicht vergessen werden die Anzahl der Blöcke um eins zu erhöhen da der erste Block die Nr. 0 hat.

sudo truncate --size$[(7403519 +1)*512] sdKarte.img

anschließend machen wir ein ls -l und siehe da:


ls -l

bekommen wir das erwartete Ergebnis:

-rw-r--r-- 1 4294967294 4294967294  3790602240 Oct 12 00:15 sdKarte.img

Die Umkehrprobe habe ich atürlich auch gemacht. Ich habe die Datei sdKarte.img auf eine andere SD Karte kopiert und einen Raspi damit gestartet. Ergo. Funktioniert.

In einem zweiten Teil werde ich das Backup als Script beschreiben, damit dies künftig alles auch schon automatisch passiert.