Automatische Datensicherung: Backup-Script mit rsync bei Einstecken einer externen Festplatte

21 Kommentare Autor: Jürgen (jdo)

TuxNachdem gestern der Wunsch nach dem Script geäußert wurde, mit dem ich beim Einstecken meiner externen USB-Backup-Festplatte meine Daten automatisch sichere, hab ich das mal (hoffentlich einigermaßen verständlich) zusammengeschrieben.

Dieses Script verwende ich unter anderem für meine eigene Datensicherung und auch bei diversen Bekannten, die den Umstieg auf Linux gewagt und auch geschafft haben. Ich weiß, dass es immer jemanden gibt, der es besser kann oder weiß, aber für mich funktioniert diese Lösung und zwar schon recht lange. Geboren wurde die Idee, weil es mir einfach zu lästig war, die Sicherung jedesmal automatisch anzustoßen – warum auch, wenn man es automatisieren kann … wobei mir da wieder der Spruch eines guten Freundes einfällt: “Ich bin Linux-Administrator, weil ich faul bin – man kann alles scripten!”

Im Prinzip ist es sehr einfach:

  • Erkenne, wenn meine externe Festplatte eingesteckt wurde
  • Führe die Datensicherung aus
  • Häng die Platte wieder aus

Nun gibt es im Prinzip zwei Wege, dieses Ziel zu erreichen. Zum Einen kann ich udev benutzen, zum anderen einen Cronjob. Für mich persönlich benutze ich die Lösung mit udev. Bei meinem Freund in der Bar den Cronjob, was ich auch begründen möchte. Er steckt die Festplatte ein und rennt dann irgendwo hin, telefoniert, macht sonst irgendwas. Somit verpasst er vielleicht den Moment, wo ihn das System benachrichtig “Backup fertig”. Das Fenster soll ihn aber so lange belästigen, bis er die Festplatte aber ausgesteckt und diese wieder an einen sicheren Ort gelegt hat. Er wollte das auch so.

Die Datensicherung war nach Absprache so geplant, dass sie einmal am Tag durchgeführt wird. Ist die Synchronisierung der wichtigsten Ordner erledigt, kommt die externe Festplatte wieder in Sicherheit. Der Cronjob läuft minütlich und prüft, ob die Festplatte angesteckt ist und die Datensicherung schon durchgeführt wurde. Ist letzteres der Fall, wird der Anwender benachrichtigt, dass er das Backup-Medium ausstecken kann – und zwar auch minütlich.

Da beide Lösungen zu selben Ziel führen, möchte ich sowohl auf die udev– als auch die Cronjob-Variante eingehen. Was Dir symphatischer ist, kannst Du dann selbst entscheiden. Eleganter ist sicher udev.

Und bevor einer schreit, möchte ich auch gleich den Nachteil meiner Backup-Methode rausstellen. Ich verwende –delete als rsync-Option. Bedeutet: Alles was nicht mehr auf der Festplatte ist, wird auf dem Sicherungs-Medium auch gelöscht. Ich habe dem Anwender eingebläut: “Wenn Dir irgendetwas ungeheuer erscheint, nicht einfach die Festplatte einstecken, sondern melden!”. Ja, es gibt viele andere Möglichkeiten mit tar, find und mtime inkrementelle Datensicherungen zu machen. Ich habe dazu im Jahre 2005 mal einen Artikel für TecChannel geschrieben, der seine Gültigkeit immer noch hat. Die Werkzeuge dafür sind in jeder Linux-Distribution vorhanden. Nehmt die nachfolgenden Script-Schnippsel also eher als Inspiration und modifiziert ganz nach belieben drauf los – viele Wege führen nach Rom! Ich benutze für das Backup das root-Konto, weil ich damit ganz einfach Zugriff auf alles habe (Daten, mounten …).

Backup mit einer Cronjob-Lösung

Zunächst einmal muss ich herausfinden, wie ich meine externe Festplatte ansprechen kann. Ich möchte diese immer im selben Verzeichnis einfinden. Am einfachsten geht das in diesen Tagen mittels der UUID. Die elegantere Lösung ist via blkid: sudo blkid /dev/sdX. Dabei ist das X mit der entsprechenden Partition zu ersetzen. Es ginge aber auch so: ls -l /dev/disk/by-uuid

Ich bin bei der Benachrichtigung auf folgendes Problem gestoßen: das root-Script hat den angemeldeten Benutzer nicht über so ein schönes Pop-Up-Fenster benachrichtigt. Viele gute Ratschläge halfen damals nicht weiter. Auch das oft beschriebene DISPLAY=:0.0 /usr/bin/notify-send brachte keinen Erfolg. Abhilfe schaffte dann ein Code-Schnippsel (notify_me-Funktion), das ich auf edv-krischer.de gefunden habe. Das schickt einfach eine Nachricht an alle an X angemeldeten Anwender.

Hinweis: notify-send funktioniert mit GNOME. Unter KDE sollte sich das mittels kdialog lösen lassen.

Nun folgt das eigentliche Script (hier als .sh-Datei herunterladbar, dann ist es etwas übersichtlicher und WordPress kann keine Zeichen vermurksen):

#!/bin/bash

notify_me() {
ALL_USER="$(users | sort)"
echo Desktop-Message to: $ALL_USER
for USER_TMP in $ALL_USER; do
if [ "$USER_TMP" = "$USER_LAST" ]; then
#if user already notified, continue
continue
fi
su $USER_TMP -c "XAUTHORITY=/home/$USER_TMP/.Xauthority DISPLAY=:0 notify-send $1 $2"
#save last username to avoid double notification
USER_LAST=$USER_TMP
done
}

########## Konfiguration ############
UUID="42d23002-497e-4ed9-9697-057a643108b8" #ist durch die eigene UUID zu ersetzen
CHECK_DISC="/dev/disk/by-uuid/$UUID"
DATE=`/bin/date +%Y%m%d`
CHECK_DATE_DIR="/root" #Verzeichnis der Datum-Steuerdatei und temporäres Einbinden der Backup-Platte
BACKUP_DIR_MEDIA="backup" #Mounte die Backup-Platte da hin
BACKUP_DIR="$CHECK_DATE_DIR/$BACKUP_DIR_MEDIA" #Backup-Verzeichnis, in dem Fall root der Backup-Platte
DATE_FILE="$CHECK_DATE_DIR/$DATE.date" #Datum-Steuerdatei, ob Backup schon durchgeführt wurde
CHECK_RSYNC=`ps -aef | grep -v grep | grep rsync | wc -l`
CHECK_MOUNT=`df -h | awk '{print $6}' | grep $BACKUP_DIR_MEDIA | wc -l`
SOURCE_DIR="/zu/sicherndes/verzeichnis/"

#####################################

/bin/umount $CHECK_DISC

if [ ! -d $CHECK_DATE_DIR/$BACKUP_DIR_MEDIA ]; then
/bin/mkdir $CHECK_DATE_DIR/$BACKUP_DIR_MEDIA
fi

if [ $CHECK_RSYNC = 0 ]; then #wenn kein anderer rsync-Prozess läuft, dann leg los
if [ -e $CHECK_DISC ]; then
if [ $CHECK_MOUNT = 0 ]; then
if [ ! -f $DATE_FILE ]; then
/bin/mount UUID=$UUID $CHECK_DATE_DIR/$BACKUP_DIR_MEDIA
sleep 5
rm -f $CHECK_DATE_DIR/*.date
notify_me "Backup\-Platte\ erkannt" "starte\ Datensicherung\ \(ich\ sag\ es\ Dir,\ wenn\ ich\ fertig\ bin\!\)"
/usr/bin/rsync -avn --delete --safe-links --ignore-errors $SOURCE_DIR $BACKUP_DIR #macht nur einen Testlauf. Für den Ernstfall -avn zu
-av ändern
/bin/sync
/usr/bin/touch $DATE_FILE
/bin/umount /dev/disk/by-uuid/$UUID
else
notify_me "Backup\ heute\ schon\ durchgefuehrt" "Du\ kannst\ die\ Festplatte\ nun\ abstecken"
fi
fi
fi
fi

Nun musst Du dem System noch mitteilen, dass es dieses Script minütlich aufrufen soll. Dazu öffnen wir die Crontab von root: sudo crontab -e und fügen folgende Zeile ein:

*/1 * * * * /root/backup.sh >> /dev/null 2>&1

Das >> /dev/null 2>&1bewirkt, dass der Cronjob keine Einträge in der Logdatei vornimmt. Jede Minute ein Eintrag ist einfach unnötig und müllt das Logfile zu.

Ein Ansatz mit udev

Im Prinzip ändert sich nicht viel am obigen Script. Man muss es wirklich nur geringfügig anpassen – das schaffst Du schon ;). Der eigentliche Unterschied ist, dass ich nicht auf cron angewiesen bin, sondern udev des Systems nutze. Allerdings kann ich dann auch nur die Fertigstellung des Backups am Ende des Scripts nur einmal ausgeben. Wenn Du notify-send die Option -t 0 mitgibst, verschwindet das Fenster erst nach einer Bestätigung. Beispiel: notify-send “Hallo” -t 0

Zunächst muss ich herausfinden, wie ich meine Festplatte ansprechen kann:

sudo udevadm info -a -p  $(udevadm info -q path -n /dev/sdX) (X ist wieder mit der entsprechenden Kennung zu ersetzen)

Mit diesem Befehl bekomme ich nun allerhand Informationen. Um die USB-Festplatte zu erkennen, verwende ich persönlich ATTRS{serial}. Um nicht lange suchen zu müssen, modifiziere ich einfach den obigen Befehl:

sudo udevadm info -a -p  $(udevadm info -q path -n /dev/sdb1) | grep serial

und bei mir kommt dann so etwas heraus:

ATTRS{serial}==”00000011E0A2F”
ATTRS{serial}==”0000:00:1d.0″

Nun muss ich udev mitteilen – führe das Backup-Script aus, wenn diese Platte an das System angeschlossen wird. Dazu legen wir im Verzeichnis /etc/udev/rules.d/ zum Beispiel eine Datei mit Namen 85-usb-festplatte.rules an. In diese schreibe ich dann in meinem Fall:

ATTRS{serial}==”00000011E0A2F”, SYMLINK+=”backup-drive”, RUN+=”/bin/sh /pfad/zu/backup.sh”

RUN ist nicht immer optimal, da udev irgendwann abbrechen würde, ist die Aktion nicht in einer bestimmten Zeit abgeschlossen. Hat man große Backups und Aktionen, die lange Zeit in Anspruch nehmen, muss man sich eine andere Methode überlegen. Man könnte udev dann nur benutzen, um das Medium einzubinden und dies von anderer Seite überwachen zu lassen. Passiert da etwas, läuft das entsprechende Skript los. Das Paket incron wäre so ein Kandidat, da man mit diesem Daemon Ordner und Dateien überwachen kann.

Das war auch schon die ganze Magie eine Datensicherung durchzuführen, wenn eine bestimmte Festplatte angeschlossen wird. Viel Spaß beim Basteln. Konstruktive Kritik und Verbesserungs-Vorschläge höre ich immer gerne, Trolle mögen bitte unter der Brücke bleiben. Wie anfangs gesagt funktioniert das Prinzip für mich schon sehr lange zuverlässig und genügt meinen Ansprüchen. Auch wenn mein Beispiel-Script für Dich vielleicht gar nicht taugt, sollte es Dir zumindest einen Ansatz geben, wie man so ein Problem lösen kann.




 Alle Kommentare als Feed abonnieren

21 Kommentare zu “Automatische Datensicherung: Backup-Script mit rsync bei Einstecken einer externen Festplatte”

  1. reisub says:

    Hallo,

    ich habe einen kleinen Tipp zur --delete Problematik. Schau dir mal den rsync-parameter --link-dest an. Damit kannst du ein altes Backupverzeichnis angeben. Im neuen Backupverzeichnis werden dann soweit möglich Hardlinks erstellt und nur geänderte Dateien gesichert.

    Gewissermaßen ein inkrementelles Backup, du kannst ohne Probleme irgendein Zwischenbackup löschen ohne dass die neueren davon beeinflusst werden.

    Mfg reisub

    • jdo says:

      Hi,

      danke für den Hinweis, ich kenne den Parameter. Allerdings ist das --delete für mich kein Problem, weil ich persönlich meine Daten gerne total synchron habe. Für meinen Kumpel haben wir damals eine Platte gesucht, die genau so groß war wie seine interne Platte. Der muss sich nun auch nicht darum kümmern, dass ihm irgendwann der Platz ausgeht.

      Der Fantasie sind in Sachen Backup-Strategie kaum Grenzen gesetzt. Und überall wird es Vor- und Nachteile geben.

  2. Karl says:

    Vielen Dank, da werde ich mich mal bald ans basteln machen.

  3. Thomas says:

    Wäre bei der UDEV Variante nicht denkbar, nach erfolgreichem Backup, ein weiteres script zu starten, welches minütlich die Notification versendet?

    Bin leider auch nicht der Scriptprofi 😉 Aber sollte doch sicherlich dort eine Möglichkeit geben, denn die UDEV Variante ist wie du selber bereits geschrieben hast, eindeutig die elegantere Lösung

    • jdo says:

      Ist auch möglich ... Das zweite Script braucht dann einfach nur eine Ausstiegsklausel, sobald die Festplatte nicht mehr angesteckt ist ...

  4. Brumm says:

    Danke für die tollen Anregungen :). 2 Verbesserungen:
    Statt 'sudo udevadm info -a -p $(udevadm info -q path -n /dev/sdb1) | grep serial' funktioniert auch 'sudo udevadm info -a -n /dev/sdx | grep serial'

    und notifiy-send funktioniert auch unter KDE

    • jdo says:

      Vielen Dank für die Hinweise, Dein udevadm ist in der Tat einfacher, schaut aber nicht so cool aus *g* ...

      ok, das mit KDE wusste ich nicht ... kannte dafür nur kdialog ... auf der anderen Seite: warum sollte die libnotify nur für GNOME klappen ... man lernt nie aus und deswegen wird mir Linux auch nicht langweilig und noch viele Jahre Spaß machen ...

      Viele Grüße,
      Jürgen

  5. Lukas says:

    Hallo!
    Vielen dank für die Ausarbeitung und Veröffentlichung. ich hatte mir das auch mal zum Problem gestellt, bzw noch etwas anders um die Dateien auf meinem Desktop und dem Laptop (und ggf noch der externen Festplatte) anzugleichen und aktuell zu halten.
    ich werde mir bei Gelegenheit sicher mal deine Lösung näher zu Gemüte führen und ausprobieren!

    • jdo says:

      dann schau Dir mal unison statt rsync an ... in Deinem Fall sollte das besser sein ...

      • Lukas says:

        Ja ich hatte damals auch unison probiert, soweit ich kam liefs auch ganz gut! hing dann aber eher an der netzwerkkonfiguration und umzug dass das alles etwas zum erliegen kam. im moment lade ich wichtige dateien manuell hin und her, da das nicht so viel ist geht das zur zeit.

  6. ronny says:

    ich bin ganz neu in diesem gebiet von Linux. nun meine frage wo muss ich überall was eintragen??

    • jdo says:

      Steht eigentlich alles im Artikel. Mir ist schon klar, dass es für einen Neuling etwas verwirrend sein kann. Aber es ist alles im Beitrag.

      • ronny says:

        also soll ich nur die UUID und das wars??

        • jdo says:

          Sorry, aber ich verstehe die Frage nicht. Die UUID identifiziert die Festplatte auf die Du sichern möchtest. Die brauchst Du natürlich, damit Du das Script an Deine Bedürfnisse anpassen kannst.

          • ronny says:

            ich habe es hinbekommen war einfach nur uuid.
            wenn ich das script starte kommt jetzt das.

            root@ProLiant-MicroServer:~# ./backup.sh
            umount: /: Gerät ist in Benutzung.
            (In einigen Fällen finden Sie verwertbare Informationen
            über die Prozesse, die dieses Gerät nutzen, mit lsof(8)
            oder fuser(1))
            Desktop-Message to: ronny ronny
            bash: notify-send: Befehl nicht gefunden
            root@ProLiant-MicroServer:~#

            warum kommt das__

          • jdo says:

            notify-send benötigst Du lediglich bei Desktop-Systemen, wenn das Programm Dir mitteilen soll, wann das Backup fertig ist. So wie ich das sehe, verwendest Du einen Server und da kannst Du Dir diese Zeile sparen. Man könnte sie allerdings mit einem E-Mail-Befehl ersetzen oder eben mit einer entsprechenden Methode, mit der Du Dich benachrichtigen lassen möchtest.

            Das andere besagt, dass das Gerät derzeit in Benutzung ist. Entweder befindest Du Dich auf der Konsole auf dem Gerät oder es wird anderweitig blockiert. Deswegen fällt der umount-Befehl auf die Nase.

  7. basti says:

    Hey. Danke für das Script. Habe mich da heute mal durchgearbeitet und die cronjob-Variante funktioniert wunderbar!

  8. MacUser89 says:

    Darf ich das Skript auch verändern? Unter welcher Lizenz steht es?

  9. Datenmuell says:

    Hi und vielen Dank für das Script. Funktioniert wunderbar.

    Ich hatte nur ein kleines Problemchen. Ich hab das auf einem Banana Pi laufen, und der hat nicht mal einen Monitor, wird also nur über ssh gewartet. Und um den "dusseligen" Büromenschen das Backup zu vereinfachen, hab ich einfach das
    notify_me "Backup\-Platte\ erkannt"... durch den Befehl:

    echo heartbeat > /sys/class/leds/green\:ph24\:led1/trigger

    ersetzt. Nun fängt bei beginn des Backups die grüne LED an zu blinken.
    Dazu muss man sagen dass ich die Led dauerhaft ausgeschaltet habe weil das ziemlich nervt.
    Dann hab ich einfach das "else" entfernt und statt.

    notify_me "Backup\ heute\ schon\ durchgefuehrt"... den Befehl:

    echo default-on > /sys/class/leds/green\:ph24\:led1/trigger

    eingetragen. Nun schaltet die Grüne LED auf Dauerlicht wenn das Backup durch ist und selbst der unwissendste Büromensch kann sehen dass er die USB-Platte abziehen oder den Pi ausmachen kann. Der Server ist nur während der Bürozeiten aktiv, weil er nur die Arbeitsverzeichnisse der einzenlen Mitarbeiter enthält.

    Des weiteren könntest Du vielleicht noch in den Beitrag einfügen, dass man bei "SOURCE_DIR" auch Mehrere Quellordner eintragen kann. Einfach durch Leerzeichen trennen. Auch könnte man noch schreiben dass, wenn man den / am Ende weglässt, der Ordner mitsamt Inhalt gesichert wird. Mit dem / am Ende wird ausschließlich der Ordnerinhalt gesichert. Könnte etwas unübersichtlich werden wenn man wie Ich, auch das /etc, /var und /srv sichert.
    Aber das kann sich eigentlich auch jeder selber zusammensuchen 🙂

    • jdo says:

      Clever ... das mit dem Licht gefällt mir 🙂

      Ja, man kann nicht alle Eventualitäten abdecken - ein bisschen selbst basteln gibt außerdem ein besseres Erfolgserlebnis 😉