Seit meinem letzten Beitrag über mein Backup-Script ist schon wieder eine Weile vergangen und ich möchte hier mal wieder den aktuellen Stand protokollieren.
#! /bin/bash
#### Diese Variablen bitte auf die eigenen Bedürfnisse anpassen
BACKUP_PFADE="/home/martin /etc /root /usr/local"
# Pfade die gesichert werden sollen
ZIELPFAD=/mnt/backup # Pfad auf dem Backupserver (ohne abschließenden /)
ZIEL_EXT=true # true = Wechseldatenträger, false = interner Speicher
ANZAHL_TAGE=7 # Tägliches Backup für x Tage
BENUTZER=martin # Benutzername auf dem Backupserver
SERVER=backup # IP-Adresse oder Hostname des Backupservers
PORT=1418 # SSH-Port des Backupservers
MAC=88:ae:1d:31:cd:17 # MAC-Adresse des Servers für WOL
EXCLUDES="--exclude .cache/ \
--exclude cache/ --exclude Cache/" # TODO: Elegantere Lösung finden
HISTORY=/root/.backup_hist # Protokoll-Datei
LISTE=/root/installed_packages.txt # Speicherort für Liste der installierten Pakete
#### Don't touch this; domdididom
#### Ab hier bitte nichts anfassen, wenn du nicht sicher weißt was du tust
MONAT=$(date +%-m)
VORMONAT=$(expr $MONAT - 1)
HOST=$(hostname)
# Backup-Server bereit?
if ! ping -c 1 $SERVER > /dev/null
then
# Backup-Server hochfahren
wakeonlan $MAC 1>/dev/null
sleep 60
if ! ping -c 1 $SERVER > /dev/null
then
echo "Backup konnte nicht durchgeführt werden. Der Server war nicht erreichbar." \
| mail -s 'Backup fehlgeschlagen!' $(whoami)@$HOST
exit
fi
fi
# Falls Zieldatenträger Wechselplatte, diese einhängen
if $ZIEL_EXT
then
ssh -p $PORT $BENUTZER\@$SERVER "sudo mount $ZIELPFAD" >/dev/null
# Datei CURRENT zur Protokollierung der aktiven Backups existiert?
if ! ssh -p $PORT $BENUTZER\@$SERVER stat $ZIELPFAD/CURRENT \> /dev/null 2\>\&1
then
ssh -p $PORT $BENUTZER\@$SERVER "touch $ZIELPFAD/CURRENT && echo "0" > $ZIELPFAD/CURRENT"
fi
# CURRENT auslesen und inkrementieren
CURRENT=$(ssh -p $PORT $BENUTZER\@$SERVER "cat $ZIELPFAD/CURRENT")
CURRENT=$(echo "$CURRENT + 1" | bc)
ssh -p $PORT $BENUTZER\@$SERVER "echo $CURRENT > $ZIELPFAD/CURRENT"
fi
# Link 0 -> 12 (für Link auf letztes Backup im Januar) existiert?
if ! ssh -p $PORT $BENUTZER\@$SERVER stat $ZIELPFAD/$HOST/0 \> /dev/null 2\>\&1
then
ssh -p $PORT $BENUTZER\@$SERVER "ln -s $ZIELPFAD/$HOST/12 $ZIELPFAD/$HOST/0"
fi
# Bei Problemen zu Testzwecken auskommentieren
# ssh -v -p $PORT $BENUTZER@$SERVER /bin/true
# Eine Liste der installierten Pakete erstellen
dpkg --get-selections > $LISTE
# Backup per rsync
for PFAD in $BACKUP_PFADE
do
rsync -az --delete-excluded $EXCLUDES --rsync-path='sudo rsync' --rsh="ssh -p $PORT" \
--link-dest=../$VORMONAT $PFAD $BENUTZER@$SERVER:$ZIELPFAD/$HOST/$MONAT
done
# Erstellen von Snapshots der letzten x Tage
ssh -p $PORT $BENUTZER\@$SERVER "sudo rm -rf $ZIELPFAD/$HOST/daily.$ANZAHL_TAGE"
if [ $ANZAHL_TAGE -gt 1 ]
then
for (( ANZAHL=$ANZAHL_TAGE ; ANZAHL >= 2 ; ANZAHL-- ))
do
ssh -p $PORT $BENUTZER\@$SERVER \
"sudo mv $ZIELPFAD/$HOST/daily.$(expr $ANZAHL - 1) $ZIELPFAD/$HOST/daily.$ANZAHL"
done
fi
if [ ! $ANZAHL_TAGE -eq 0 ]
then
ssh -p $PORT $BENUTZER\@$SERVER "sudo mv $ZIELPFAD/$HOST/daily.latest $ZIELPFAD/$HOST/daily.1"
ssh -p $PORT $BENUTZER\@$SERVER "sudo cp -al $ZIELPFAD/$HOST/$MONAT $ZIELPFAD/$HOST/daily.latest"
fi
# Falls Zieldatenträger Wechselplatte, diese aushängen sofern kein weiteres Backup aktiv ist (Variable Current)
if $ZIEL_EXT
then
CURRENT=$(ssh -p $PORT $BENUTZER\@$SERVER "cat $ZIELPFAD/CURRENT")
if [ $CURRENT -eq 1 ]
then
ssh -p $PORT $BENUTZER\@$SERVER "echo "0" > $ZIELPFAD/CURRENT"
ssh -p $PORT $BENUTZER\@$SERVER "sudo umount $ZIELPFAD" >/dev/null
else
CURRENT=$(echo "$CURRENT - 1" | bc)
ssh -p $PORT $BENUTZER\@$SERVER "echo "$CURRENT" > $ZIELPFAD/CURRENT"
fi
fi
# Datum und Uhrzeit des Backups protokollieren
date >> $HISTORY
Das Script sorgt dafür, dass mein home /home/martin
, sowie /etc
und /usr/local/bin
gesichert werden.
Ich habe auch eine Rotation eingebaut, die mir erlaubt auf einen Snapshot der letzten 7 Sicherungen zuzugreifen und es werden Snapshots der letzten 11 Monate aufbewahrt.
Durch Nutzung von Hardlinks reduziere ich den Speicherplatzverbauch auf ein Minimum.
Das Script ist darauf ausgelegt den Backup-Server per WOL aufzuwecken, eine externe Festplatte zu mounten und das Backup durchzuführen. Das mag ein recht spezifisches Setup sein, aber vielleicht kann es ja mal jemand brauchen oder zumindest Teile davon für eigene Scripte recyclen.
Dieses Script wird einmal täglich von anacron aufgerufen und sorgt dafür, dass ich mich nicht mehr bewusst um Backups kümmern muss.
Angefangen hat das Script als einfaches rsync-Kommando das mein
Home-Verzeichnis /home/martin
per SSH auf eine USB-Festplatte auf
meinem Server kopiert hat. Mit der Zeit habe ich aber immer mehr
Verbesserungen vorgenommen und es ist eine recht gute Backup-Lösung
geworden.