Backups mit rsnapshot auf ein via NFSv4 gemoutetes NAS

Backups, die Lebensretter der digitalen Zeit. Bilder, Dokumente, einfach Alles liegt in digitaler Form vor und es wäre für die meisten Menschen eine Katastrophe diese Daten zu verlieren.

Ich muss zugeben, dass die Backups von meinen privaten Systemen in der Vergangenheit immer mal wieder erhebliche Lücken aufwiesen haben. Das lag dran, dass ich bis jetzt noch keine Lösung gefunden hatte, die mich wirklich zufriedengestellt hat. Daher wurden die Backups auch nur semi automatisch erstellt. Aber mal ehrlich, Backups sind nur dann hilfreich, wenn sie regelmäßig erstellt werden und das ohne ein manuelles Eingreifen. Nachdem ich auf Twitter mal gefragt habe, was denn so die Leute in meinem Umfeld zur Datensicherung nutzen, war mit rsnapshot doch recht schnell ein Favorit zu erkennen. Ich glaube sogar, mir schon mal rsnapshot angeguckt zu haben, aber irgendwie ist dann doch nichts draus geworden.

Dieser Post wird jetzt auch keine Anleitung wie man rsnapshot einrichtet, denn dafür gibt es im Netz genug gute Anleitungen, wie zum Beispiel die im Ubuntuusers Forum. Die Kurzfassung ist, das rsnapshot durch einen Daemon wie Cron regelmäßig aufgerufen wird und sich dann um das Backup inklusive dem Rotieren der alten Backups kümmert. Damit der Speicher bei den regelmäßigen Backups nicht zu schnell aufgebraucht ist, macht rsnapshot, dass intern rsync und einige weitere Unix Kommandos wie cp nutzt, in der Regel nach einer initialen Vollsicherung aller Daten nur noch Sicherungen der geänderten Dateien und setzt auf die unveränderten Daten einen Hardlink. So hat man immer ein Verzeichnis indem alle Daten für einen bestimmten Sicherungszeitpunkt liegen.

Soweit so schön, aber das ist ja nicht der Grund, warum ich das jetzt hier in den Blog gieße. Es geht um die Stolperfallen, die sich auf dem weg zu einem funktionierenden Backup aufgetan haben. Die Erste war nicht mal direkt ein Problem, sondern eher ein Feature das ich gerne hätte. Da ich rsnapshot auch auf meinem Desktop nutze und nicht möchte das ich korrupte Backups bekomme, nur weil ich den Rechner währen dem Backup in den Suspend schicke oder herunterfahre brauche ich eine Lösung die das verhindert.
Rsnapshot legt bei jedem Start standardmäßig ein PID-file unter /var/run an, um zu verhindern, dass es noch einmal ausgeführt wird, bevor das vorherige Backup abgeschlossen wurde. Diese Datei nutze ich auch um das ungewollte Ausschalten des Rechners zu verhinder. Dazu nutze ich die von dem pm-utils bereitgestellte Möglichkeit von Hooks, die automatisch zum Beispiel beim Suspend ausgeführt werden.

Mein Hook inkl. ein paar Demo Kommentaren sieht dabei so aus:

#!/bin/bash
case $1 in
    hibernate)
        echo "Hey guys, we are going to suspend to disk!"
    ;;
    suspend)
	if [ -a /var/run/rsnapshot.pid ]; then
		exit 1;
	fi
    ;;
    thaw)
        echo "Oh, suspend to disk is over, we are resuming..."
    ;;
    resume)
        echo "Hey, the suspend to RAM seems to be over..."
    ;;
    *)  echo "Somebody is calling me totally wrong."
    ;;
esac

Der Hook sorgt somit nur dafür, dass das Script mit einem anderen Wert als Null beendet wird. Das führt dann dazu, dass das Wechseln in den Suspend abgebrochen wird. Schwups kein Problem mehr. Jedoch kommt jetzt das Problem das der Rechner dadurch häufiger mal nachts oder tagsüber läuft obwohl ich am schlafen oder unterwegs bin. Am besten wäre es doch, wenn sich der Rechner automatisch ausschaltet, wenn das Backup fertig ist, aber ohne das dies passiert, wenn ich am Rechner arbeite. Dazu nutze ich die beiden Konfigurationsoptionen cmd_preexec und cmd_postexec.

Zuerst habe ich mir einen neuen shutdown Befehl gebaut, der seinerseits noch mal prüft, ob rsnapshot gerade läuft. Wenn dies der Fall ist, legt das Script eine leer Datei an. Ein weiteres Script, dass die Routine für das Abschalten des Rechners enthält, prüft dann, ob dies Datei existiert und schaltet den Rechner nur dann aus, wenn die Datei tatsächlich existiert.
Die Variante ist nötig, da rsnapshot meistens mit den Berechtigungen des root Users läuft und man mit diesen Rechten nicht blind irgendwelche Scripte von einem normalen Nutzer ausführen möchte.
Jetzt kommen die oben erwähnten Konfigurationsoptionen zum Einsatz. cmd_postexec ruft nach dem erfolgreichen Backup das Script zum herunterfahren auf, das dann prüft ob in der Zwischenzeit der Befehl zum herunterfahren gegeben wurde (Datei existiert). Vor jedem Backup wird die Datei, die als Indikator dient, durch einen entsprechendem Befehl mit der Option cmd_preexec gelöscht. So wird der Rechner nur heruntergefahren, wenn das Kommando dazu während dem Backup gegeben wurde. Wenn kein Backup läuft, fährt der Rechner wie gewohnt direkt herunter.

Das nächste Problem war die Sicherung in ein via NFSv4 gemountetes Verzeichnis, denn rsnapshot bzw. rsync ist immer nach einer bestimmten Zeit, bei einer immer gleichen Datei hängen geblieben. Nach langem langem Debuggen mit strace und Konsorten, stand ich dann ziemlich ratlos da. Zum Glück hat mir Feli dann über Twitter den entscheidenden Tipp gegeben. Das TCP Offloading. Eigentlich dafür gedacht, um bestimmte Operationen auf dem Netzwerkstream direkt auf den Controller der Netzwerkkarte auszulagern, um die CPU zu entlasten, hat hier Probleme gemacht. Nach dem Deaktivieren des Offloadings war ich dann schon mal einen Schritt weiter und das Backup hat sich nicht immer wieder aufgehängt. Leider war das Problem damit noch nicht behoben, denn jetzt ging es mit Problemen bei den Berechtigungen weiter, denn rsnapshot versucht standardmäßig die Dateiberechtigungen bei zu behalten.

Unter NFSv4 hat sich das System mit dem User IDs auf Nutzer gemappt werden geändert. Es wird nicht mehr einfach nur die User ID verwendet, sondern eine Kombination aus Nutzername, ID und dem Namen der Domäne in der sich der Client und der NFS-Server befinden. Das war aus historischen Gründen bei mir nicht der Fall, daher habe ich die Domänennamen angeglichen. Alternativ hätte ich auch den Entsprechenden Wert in der Konfigurationsdatei des ID Mappers idmapd ändern können. Das hätte dann wie folgt ausgesehen:

[General]

Verbosity = 0
Pipefs-Directory = /run/rpc_pipefs
# set your own domain here, if id differs from FQDN minus hostname
Domain = example.com

[Mapping]

Nobody-User = nobody
Nobody-Group = nogroup

Texte die das nochmal genauer Beschreiben finden sich bei SUSE hier und hier.

Als letzes Hindernis ist mir dann noch beim cp -al Befehl, der die Hardlinks für die alte Version des Backups unter rsnapshot anlegt, der nfsd, also der NFS Server Daemon um die Ohren geflogen. Das liegt daran, dass wie in diesem Bug Report nachzulesen der NFS-Server bei dem Befehl set_nfsv4_acl_one versucht, einen Null-pointer zu dereferenzieren, was natürlich schiefgehen muss. Nach einem Update auf eine Kernel Version > 3.2.63-1 und einem Reboot war das Problem dann auch behoben. Jetzt läuft mein Backup ganz entspannt und ohne das ich was machen muss im Hintergrund.

Und denkt immer dran ein Backup zu machen und die Platte auf der das liegt im Idealfall nicht direkt neben eurem Rechner liegen zu lassen, sondern mindesten eine Kopie irgendwo außerhalb der eigenen vier Wände aufzubewahren.

Zu letzt sei aber noch eins gesagt: Kein Backup? Kein Mitleid!