sophisticated Backups mit Rsync
Backups sind wichtig.
Jeder der einmal vor einer kaputten, ratternden Festplatte gesessen hat, weiß wie frustrierend das Wissen ist, alle seine Daten ins informationstechnische Nirwana entschwinden zu sehen.
Ist ein Backup der persönlichen Daten noch mit relativ geringem Aufwand möglich (so es denn regelmäßig veranstaltet wird), so wird ein Backup eines Server-Systems in vielen Dingen anspruchsvoller.
Dies fängt damit an, dass reinen Datenmengen oftmals das Vielfache eines Ein-Benutzer-Systems betragen. Okay in heutige Zeit, wo ein jeder zig GBs an Musik und Videos auf dem Rechner hat, muss man das natürlich relativieren.
In diesem Beitrag möchte ich ein Bash-Script vorstellen, welches folgende Dinge leistet:
- Sichern von N-Hosts über RSYNC
- Sichern von N-Verzeichnissen auf jedem Host
- Inkrementelles Sichern (es werden nur Unterschiede gesichert/übertragen)
- Zusammenführen von täglichen (inkrementellen) Backups zu wöchentlichen Vollbackups.
- die aktuellen Backups sind jeweils unter einem Hardlink “latest” erreichbar.
Nachfolgend erfolgt eine Beschreibung über den Ablauf des Scriptes.
Es wird Momentan durch eine Sicherung von 3 Serversystemen und ca. 20 GB an reinen Nutzdaten getestet.
- Stelle sicher, dass alle notwendigen Verzeichnisse vorhanden sind:
- Verzeichnis “log” für log-Dateien der Sicherungen
- Verzeichnis “backup” für die eigentlichen Sicherungen
- Je Backupquelle ein Verzeichnis
- Innerhalb jedes Quellverzeichnisses ein Verzeichnis für tägliche und eines für wöchentliche Sicherungen
- Stelle sicher, dass alle Config-Dateien vorhanden sind:
- sources.txt mit den Namen der zu sichernden Hosts/Verzeichnisse
- exclude.txt mit den Dateien, welche nicht gesichert werden sollten (z.B. Thumbs.db)
- innerhalb jedes Quellverzeichnisses eine Datei namens src-root.txt (mit dem ROOT der Sicherung)
und src-folders.txt (mit den einzelnen Verzeichnissen)
Der Aufbau des Root-Verzeichnisses sieht nun wie folgt aus.
ROOT | |-log |-sources.txt |-exclude.txt |-backup |-host1.de |-host2.de |-src-root.txt |-src-folders.txt |-daily |-weekly
Ein Beispiel für eine sources.txt sieht wie folgt aus:
host1.de host2.de
Ein Beispiel für eine exclude.txt sieht wie folgt aus:
Thumbs.db .DS_Store
Eine src-root.txt könnte so aussehen:
user@host1.de:
Eine src-folders.txt könnte so aussehen:
/home /etc /var/log /var/www
Ablauf der Sicherung:
- Generiere Log-Datei.
- Iteriere über alle Quellen aus sources.txt
- Überprüfe ob alle Quellen Verzeichnisse zum Sichern enthalten.
- Überprüfe ob lokal Verzeichnisse für die Sicherung existieren – wenn nicht lege sie an.
- Erstelle tägliches Backup – existiert ein vorheriges Backup, so sichere nur die Änderungen.
Dies passiert mit folgendem Befehl:
rsync -zrva –exclude-from=exclude.txt –link-dest=<hardlink-zu-altem-backup> <sourcefolder>/ <backupfolder>/daily/<tag>/<zu-sicherndes-Verzeichnis>
Hierbei werden alle Benutzerrechte mitgesichert.
Setzte Hardlink vom letztem täglichen Backup auf aktuelles tägliches Backup.
Überprüfe ob Sonntag ist ( date +%w = 0)
Wenn ja, synchronisiere letztes tägliches Backup mit wöchentlichem (neuen) Backup.
Setzte Hardlink vom letztem wöchentlichen Backup auf aktuelles wöchentliches Backup.
Lösche alle täglichen Backups.
Setzte Hardlink vom letztem täglichen Backup auf aktuelles wöchentliches Backup.
So werden maximal 7 tägliche inkrementelle Backups erstellt und pro Jahr 52 wöchentliche Full-Backups.
#!/bin/sh # Philipp's backup-scripte version 2 ROOT=/tank/backup/server BACKDIR=$ROOT/backup D=`eval date +%Y-%m-%d` W=`eval date +%Y-%W` w=`eval date +%w` LATEST=latest EXCLUDE=$ROOT/exclude.txt SOURCES=$ROOT/sources.txt LOG=$ROOT/log/$D.log # Array of all needed folders folders=( $ROOT/log $ROOT/sources ) files=( $EXCLUDE $SOURCES $LOG) for folder in ${folders[@]}; do if [ ! -d $folder ] ; then mkdir -p $folder; fi done for file in ${files[@]}; do if [ ! -f $file ] ; then touch $file; fi done log () { if [ -z "$1" ] ; then echo "" > $LOG ; fi echo $1 echo $1 >> $LOG } # Ab hier gehts dann richtig los :-) log log "STARTING BACKUP..." log "date: $D" #stopping start time #TIME0= expr `date +%s`; # backup following sources for SOURCE in `cat $SOURCES`; do log "" log "==================================================================" log "====== backup: $SOURCE " if [ ! -d $BACKDIR/$SOURCE/daily/$D ] ; then mkdir -p $BACKDIR/$SOURCE/daily/$D; fi if [ ! -f $BACKDIR/$SOURCE/src-root.txt ] ; then touch $BACKDIR/$SOURCE/src-root.txt; fi if [ ! -f $BACKDIR/$SOURCE/src-folders.txt ] ; then touch $BACKDIR/$SOURCE/src-folders.txt; fi #Logindaten lesen LOGINDATA=`cat $BACKDIR/$SOURCE/src-root.txt` if [ ! "$LOGINDATA" = "" ]; then log "====== benutze $LOGINDATA" log "==================================================================" log "" for FOLDER in `cat $BACKDIR/$SOURCE/src-folders.txt`; do log "backup up... $FOLDER" mkdir -p $BACKDIR/$SOURCE/daily/$D/$FOLDER ### wenn schon latest-day vorhanden, dann sichere nur ânderungen if [ ! -d $BACKDIR/$SOURCE/daily/$LATEST ] ; then rsync -zrva $OLD --exclude-from=$EXCLUDE --link-dest=$BACKDIR/$SOURCE/daily/$LATEST/$FOLDER $LOGINDATA/$FOLDER/ $BACKDIR/$SOURCE/daily/$D/$FOLDER | tee -a $LOG else rsync -zrva $OLD --exclude-from=$EXCLUDE $LOGINDATA/$FOLDER/ $BACKDIR/$SOURCE/daily/$D/$FOLDER | tee -a $LOG fi done ### setze latest-day von altem Stand auf aktuelles Backup if [ -d $BACKDIR/$SOURCE/daily/$D ] ; then if [ -d $BACKDIR/$SOURCE/daily/$LATEST ] ; then rm $BACKDIR/$SOURCE/daily/$LATEST; fi ln -s $BACKDIR/$SOURCE/daily/$D $BACKDIR/$SOURCE/daily/$LATEST fi ## wenn ende der Woche, dann erstelle Snapshot der Woche if [ "$w" = "0" ]; then log "create week-backup for $W" for FOLDER in `cat $BACKDIR/$SOURCE/src-folders.txt`; do mkdir -p $BACKDIR/$SOURCE/weekly/$W/$FOLDER rsync -zrva $OLD --exclude-from=$EXCLUDE $BACKDIR/$SOURCE/daily/$D/$FOLDER/ $BACKDIR/$SOURCE/weekly/$W/$FOLDER | tee -a $LOG done ### setze latest-week von altem Stand auf aktuelles Backup if [ -d $BACKDIR/$SOURCE/weekly/$LATEST ] ; then rm $BACKDIR/$SOURCE/weekly/$LATEST; fi ln -s $BACKDIR/$SOURCE/weekly/$W $BACKDIR/$SOURCE/weekly/$LATEST | tee -a $LOG log "updating weekly latest" ### lââsche alte Backups log "delete all daily folders" rm -R $BACKDIR/$SOURCE/daily/* ### setze latest-day von altem Stand auf aktuelles Backup if [ -d $BACKDIR/$SOURCE/daily/$LATEST ] ; then rm $BACKDIR/$SOURCE/daily/$LATEST; fi ln -s $BACKDIR/$SOURCE/weekly/$W $BACKDIR/$SOURCE/daily/$LATEST | tee -a $LOG log "updating daily latest" fi fi done #stopping end time #TIME1= expr `date +%s`; #ERG = expr `$TIME1 - $TIME0`; log "==================================================================" log "DONE" #log "using $ERG seconds" log "=================================================================="