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 "=================================================================="