Datensicherung: Simples Backup via rSync

{DIV(align=>left, width=>25%, float=>right, class="umijabox")}{DIV}

Einleitung, Links

Backup) hat auf unterschiedlichen Rechnern zu unterschiedlichen Zwecken unterschiedliche howto:backup)-Skripte auf Basis von ((u:RSync am Laufen. Er findet das komischerweise einfacher, als eine daf├╝r konzipierte Software auf- und einzusetzen. Wer diese Auffassung sinnvollerweise nicht teilt, sollte sich folgende Projekte mal ansehen:

Wer gerne seine Freizeit damit verschei├čt, mit Enterprise-Grade OSS (Open Source Software) zu spielen, sei verwiesen auf

Weiterhin w├Ąre wohl zu bemerken, dass es sich hier um eine ganz brauchbare L├Âsung f├╝r die Sicherung von, ├Ąh, Dokumentdaten? handelt (also zB dem $HOME oder einfach ganz /home oder vielleicht noch /etc, aber nicht /usr/lib oder c:\windos\system32). Betriebssystempartitionen sollte man anders sichern. (Oder, die m├Ąnnlichere Variante, einfach drauf schei├čen). (Rationale: rsync kann, wenn mans nicht als super user ausf├╝hrt oder sonst irgendwelche Ma├čnahmen trifft, keine ownerships sichern. F├╝r daten, die sich selten ├Ąndern, w├Ąre au├čerdem Kompression sicher sinnvoll. D.h. doch lieber tar oder cpio f├╝r sowas nehmen, w├╝rde ich empfehlen.)

Jetzt aber los...

Die Idee

Die Idee hinter dem Skript ist, u:RSync, ein recht m├Ąchtiges Tool zum Kopieren von Dateien, regelm├Ą├čig (zB. ein mal am Tag) mit den "richtigen" Parametern zu starten, um (schnell, d.h. effizient) eine sinnvolle Datensicherung erstellen zu k├Ânnen.

Dazu wird die --backup bzw. --backup-dir Funktion von rSync gebraucht: Wenn sie gesetzt ist, ├╝berschreibt rSync obsolete Dateien beim Kopiervorgang nicht, sondern verschiebt sie in das per --backup-dir angegebene Verzeichnis.

Wenn man diesem --backup-dir Parameter jeden Tag einfach das Datum nach ISO r├╝ckw├Ąrts mitgibt (heute zB 2009-10-12) erh├Ąlt man einen Verzeichnisbaum, der einerseits das aktuellste Backup immer komplett vorh├Ąlt, aber alte Versionen archiviert anstatt l├Âscht. Man k├Ânnte das wohl als ┬╗r├╝ckw├Ąrts inkrementelle┬ź Datensicherung bezeichnen (im Gegensatz zu Backup auf Tapes, wo man ein mal / regelm├Ą├čig ein volles Backup erstellt und dann die ├änderungen, die da drauf kommen, jeden Tag irgendwie wegspeichert. Um dann den letzten Stand zu bekommen braucht man die komplette Sicherung vom WE plus die inkrementellen Sicherungen von jedem Wochentag... nervig).

Vorteile

Der gr├Â├čte Vorteil, den Flo darin sieht, ist der leichte Zugriff auf die Datensicherung sowie das Archiv: Suche ich eine Datei, deren Namen ich kenne, benutze ich die normale Dateisystem-Suche (unter Unix also find oder locate) und bekomme eine Liste mit gesicherten Versionen dieser Datei zur├╝ck.

Au├čerdem ist das Backup schnell wie H├Âlle (genaueres siehe zB bei "Windows" weiter unten).

Nachteile

Der gr├Â├čte Nachteil ist wohl, dass es nicht sehr leicht f├Ąllt, den exakten Stand einer kompletten, aber veralteten Sicherung herzustellen. Das war mir bisher aber immer egal: Wie oben erw├Ąhnt handelt es sich um eine Sicherung meines $HOMEs.

Verwendung

Ich habe die Skripte bei mir unter /usr/local/sbin gespeichert und rufe sie per cron auf: Auf meiner Workstation durch einen Eintrag in cron.daily (damit das Backup ein mal am Tag gemacht wird, egal wann), auf dem fuckup per Eintrag in der crontab (damit das Backup zu einer definierten Zeit nachts passiert).

Speziell auf der Workstation ist es sinnvoll, dem Skript eine niedrige Priorit├Ąt mitzugeben. Per ionice auch f├╝r io. (Getestet unter Linux) nice -n 15 ionice -c3 /usr/local/sbin/backup-home.sh

Essenz

Das wichtige an dem Skript ist: /usr/bin/rsync --delete --backup --backup-dir=$DST_INCR/date +%Y-%m-%d $SRC $DST_MAIN

Das komplette Skript - Fuckup Musiksammlung

Die hier aufgef├╝hrte Variante wird zum Sichern der Musiksammlung vom Fuckup auf eine andere Maschine via DSL ("off-site backup") verwendet.

Inkl einem einfachen, "gut genug" funktionierendem "versuchs nochmal wenn die DSL Leitung abgekackt ist" Teil, einem "schreib eine Mail mit dem Logfile an Flo"-Teil und etwas unn├Âtigen Ballast aus ├Ąlteren Versionen:

Download des Skripts (zip-Archiv).

{CODE()}

#!/bin/bash # # Scope: Backup Flos Home Directory to another Drive (or Machine) #

### Config SRC="/data/export/Audio" DST_MAIN="user@remote.host.net:/storage/fuckupmirror/aktuell/" DST_INCR="/storage/fuckupmirror/archiv/date +%Y-%m-%d/" DST_LOG="/home/CyberSync/log/date +%Y-%m-%d.log" REPORT_RCPT="your.email@address.com" RSYNC_OPTS="--bwlimit=60 --ignore-errors --delete --backup --backup-dir=$DST_INCR -av --one-file-system" PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ID_STRING="hostname echo $0 | sed 's/\/.*\///'" ### /Config

### see http://www.davidpashley.com/articles/writing-robust-shell-scripts.html set -u

### define custom routines function failexit() { echo "Something went wrong, let's bail out! Sending mail report to $REPORT_RCPT..." mail -s "$ID_STRING: ERROR REASON: $1." $REPORT_RCPT < $DST_LOG cd / exit 1 }

function cleanexit() { # clean exit; remount volume read-only again. sync sleep 5 mail -s "$ID_STRING: OK. Der Vogel ist gelandet." $REPORT_RCPT < $DST_LOG exit 0 }

function commit() { trap "killall rsync; failexit \"Caught signal\"" INT TERM echo "Initiating transfer on date..." >> $DST_LOG rsync $RSYNC_OPTS $SRC $DST_MAIN 2>&1 >> $DST_LOG RSYNC_EXITCODE=$? echo "rsync exit code: $RSYNC_EXITCODE" >> $DST_LOG echo "finished on date." >> $DST_LOG trap - INT TERM }

# do it commit

### action depending on return status of rsync. see rsync man page for a list of exit codes # Success if [ $RSYNC_EXITCODE -eq 0 ]; then cleanexit; fi # 12 happens when the DSL link dies. retry! if [ $RSYNC_EXITCODE -eq 12 ]; then commit; fi # Received SIGINT, SIGTERM, SIGHUP if [ $RSYNC_EXITCODE -eq 20 ]; then failexit "Caught Signal"; fi # Partial transfer due to error if [ $RSYNC_EXITCODE -eq 23 ]; then cleanexit; fi # Partial transfer due to vanished source files if [ $RSYNC_EXITCODE -eq 24 ]; then cleanexit; fi # 255 happens to me when SSH dies. retry! if [ $RSYNC_EXITCODE -eq 255 ]; then commit; fi # "else" failexit "Unknown, have a look at the logfile."

# eof #


{CODE}

Das komplette Skript - Flos Workstation /home

Inkl. "Exclude"-Direktiven f├╝r Zeug wie Browsercaches und Bittorrent-Download-Ordner, was ich nicht sichern will. Speichert einfach auf eine zweite Platte in meinem Rechner. Die aktuelle Sicherung von dort kopieren ich 'manchmal' nach off-site, aber das macht ein anderes Skript.

Download des Skripts (zip-Archiv).

{CODE()}

#!/bin/bash # # Scope: Backup Flos Home Directory to another Drive (or Machine) #

### Config SRC="/home/" DST_ROOT="/mnt/backup" DST_MAIN="$DST_ROOT/aktuell/jimi/home" DST_INCR="$DST_ROOT/archiv/date +%Y-%m-%d/jimi/home" DST_LOG="$DST_ROOT/archiv/date +%Y-%m-%d/jimi/home-date +%Y-%m-%d.log" EXCLUDES="/usr/local/sbin/backup-home-exclude.list" REPORT_RCPT="mailaddress@recipient.net" RSYNC_OPTS="--force --ignore-errors --delete --delete-excluded --exclude-from=$EXCLUDES --backup --backup-dir=$DST_INCR -av --one-file-system" MOUNT_CHK="/dev/sda3 on /mnt/backup type ext3 (rw,noatime)" PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ID_STRING="hostname echo $0 | sed 's/\/.*\///'" ### Config Ende

### define custom routines function failexit() { echo "Something went wrong, let's bail out! Sending mail report to $REPORT_RCPT..." mail -s "$ID_STRING : ERROR REASON: $1." $REPORT_RCPT < /dev/null mail -s "$ID_STRING : LOGFILE." $REPORT_RCPT < $DST_LOG cd / mount -o remount,ro $DST_ROOT exit 1 } function cleanexit() { # clean exit; remount volume read-only again. sync sleep 5 mount -o remount,ro $DST_ROOT mail -s "$ID_STRING : OK. Die Eier sind fein." $REPORT_RCPT < $DST_LOG exit 0 }

### make volume writable mount -o remount,rw $DST_ROOT

### sanity checks if ! [ e2label /dev/sda3 = "backup" ]; then failexit "FATAL ERROR: /dev/sda3 is not labelled correctly. Will not backup to the wrong disk"; fi if ! [ -f $EXCLUDES ]; then failexit "FATAL ERROR: $EXCLUDES does not exist"; fi if ! mount | fgrep -s -q "$MOUNTCHK" ; then failexit "FATAL ERROR: Check mount options"; fi

### commit install -d $DST_INCR || failexit "Unable to create directories" install -d $DST_MAIN || failexit "Unable to create directories" echo "Initiating transfer on date ..." > $DST_LOG rsync $RSYNC_OPTS $SRC $DST_MAIN 2>&1 >> $DST_LOG RSYNC_EXITCODE=$? echo "finished on date ." >> $DST_LOG

### action depending on return status of rsync. see rsync man page for a list of exit codes # Success if [ $RSYNC_EXITCODE -eq 0 ]; then cleanexit; fi # Received SIGUSR1 or SIGINT # (probably we interactively killed rsync because it ate our resources) if [ $RSYNC_EXITCODE -eq 20 ]; then cleanexit; fi # Partial transfer due to error if [ $RSYNC_EXITCODE -eq 23 ]; then cleanexit; fi # Partial transfer due to vanished source files if [ $RSYNC_EXITCODE -eq 24 ]; then cleanexit; fi # "else" failexit "Unknown, have a look at the logfile."

# eof #

{CODE} Die ┬╗backup-home-exclude.list┬ź sieht dabei so aus: {CODE()} .thumbnails/ cache/* Cache/* .opera/cache4/* .gvfs urlclassifier3.sqlite CACHE* Desktop/torrent/* Trash/* {CODE}

Schnelles Backup f├╝r Windows...

Ich hab auch f├╝r Windows ein ├Ąhnliches Skript geschrieben, allerdings knapper und in Python und nicht durch Cron sondern durch eine Verkn├╝pfung am Desktop zu starten. Damit kann man schnell seine "Dokumente und Einstellungen" (also $HOME) auf zB eine extern USB Platte sichern. Urspr├╝nglich wollte ich kein eigenes Skript inkl. Interpreter etc. hernehmen, aber ich wei├č nicht, wie ich unter XP sonst das aktuelle Datum als Parameter ├╝bergeben kann.

Wie schnell?

Auf Consls altem Laptop, der nur USB 1.1 kann - das Backup l├Ąuft auf eine via USB 1.1 auf eine externe Platte - braucht das (inkrementelle) Backup ihres gesamten "Dokumente und Einstellungen" Ordners (aktuell ~ 20 GB, normalerweise werden nur 40 MB oder so neu gesichert) typischerweise weniger als eine Minute. Das ist sehr fix, weil da ja halt schon viele sehr kleine Dateien enthalten sind, die ├╝berpr├╝ft werden m├╝ssen (mehrere tausend). (Die eine Minute nat├╝rlich ohne das vorher schon mal gemacht zu haben, also ohne Datei-Cache, sonst w├Ąr das ja nichts besonderes...). Das finde ich sehr, sehr schnell.

Wo krieg ich das her?

Um das zum Laufen zu bringen, braucht man einen Python-Interpreter, CWRsync (evtl. plus UTF8 Fix ) und fuer die "Fertig!" Nachricht am Ende EasyGUI.

(Update 2010-02: Es gibt auch einen nativen Port von RSync f├╝r Win32, der hat wahrscheinlich kein Problem mit UTF-8? Und: Evtl ist DeltaCopy h├╝bscher? Das k├Ânnte auch ein rsync f├╝r Windows dabei haben, aber unter "inkremental backup" verstehen die anscheinend den delta-algorithmus von rsync bezogen auf die ├╝bertragung, nicht die tatsache, dass mann die alten daten vielleicht auch aufheben will)

Und nat├╝rlich das Skript selbst: Download des Skripts.


howto