Einführung
Da es für mich keine passende Backup-Lösung gab, habe ich mir diese selber
geschrieben. Meine Daten werden jetzt per rsync
auf meinen Backup-Server
synchronisiert. Für meine Backup-Lösung braucht man nicht zwingend einen
Backup-Server. Mit rsync
kann man auch auf dem lokalen Rechner Dateien und
Verzeichnisse synchronisieren.
Das tolle an meinem Skript ist, dass ich verschiedene Versionen von meinen Daten habe. Wenn ich eine Datei lösche und dann mein Backup starte, wird diese Datei auf dem Backup-Server nicht gelöscht! Dies geschieht mit Hardlinks. Das geniale daran ist, dass nur die neuen Daten neuen Platz auf der Harddisk beanspruchen. Obwohl ich über 10 mal die selbe Datei gesichert habe, wird deren Speicherplatz nur einmal belegt.
Voraussetzung
Meine Backuplösung basiert auf diversen Bash-Skripten. Diese müssen mit den nötigen Rechten ausgeführt werden können. Will man die Daten auf einen Server sichern, benötigt man dort ein SSH-Login. Am einfachsten geht dies mit Public-/Private-Keys, damit man nicht jedes mal ein Passwort eingeben muss.
Als Client benutze ich mein Lenovo Thinkpad T61 Notebook und mein Asus EEEPC 1000H Netbook, welche beide mit Arch Linux laufen. Bei meinem Backup-Server handelt es sich um eine Asus EEEBOX, welche mit Debian 5.0 läuft. Das Backup-Skript sollte jedoch auf jedem Linux lauffähig sein.
Übersicht
Hier eine kleine übersicht über mein Backup-Konzept:
Komponenten
Mein Backup-Script benötigt folgende Komponenten:
install_
: Installiert die Verzeichnisstruktur für die Backups auf dem Server/Computercrontab
: Die Einträge in der Crontab rufen das Backup-Script auf dem Server auf. Dies kann aber auch manuell gemacht werden.backup
: Dieses Skript kopiert die Backup Ordner und ermöglicht so eine Versionierungsyncup
: Mit diesem Skript werden meine Daten auf den Server synchronisiertsyncup.conf
: Wird syncup ohne Parameter aufgerufen, werden die in dieser Datei angegebenen Dateien und Verzeichnisse gesichert.
Installation
Das Installationsskript install
erstellt folgende Ordner:
- backupdata_: Hier werden die zu sichernden Daten abgespeichert
daily_1
bisdaily_7
: Eine Version der Daten von den letzten sieben Tagenweekly_1
bisweekly_4
: Eine Version der Daten von den letzten vier Wochenmonthly_1
bismonthly_12
: Eine Version der Daten von den letzten zwölf Monatenyearly_1
bisyearly_5
: Eine Version der Daten von den letzten fünf Halbjahren
Folgendes Skript erstellt mir die Ordnerstruktur:
#!/usr/bin/env bash
################################################################
#
# install
# Erstellt die Verzeichnisse fuer backup
#
# Copyright 2010 Emanuel Duss
# Licensed under GNU General Public License
#
# 2009-12-05; Emanuel Duss; Erste Version
#
################################################################
################################################################
# Main
cd /media/backup/backup/
# Ordner fuer die Synchronisation
mkdir backupdata
# Ordner fuer taegliche Backups
for i in `seq 1 7`
do
mkdir daily_$i
done
# Ordner fuer woechentliche Backups
for i in `seq 1 4`
do
mkdir weekly_$i
done
# Ordner fuer monatliche Backups
for i in `seq 1 12`
do
mkdir monthly_$i
done
# Ordner fuer halbjaehrliche Backups
for i in `seq 1 5`
do
mkdir yearly_$i
done
# EOF
Synchronisation
Das Skript syncup
synchronisiert die als Parameter angegebene Verzeichnisse
und Dateien auf meinen Backup-Server. Werden keine Parameter angegeben, werden
die Dateien und Verzeichnisse aus dem Konfigurationsfile syncup.conf
gesichert. Will man keinen Backup-Server nutzen, sondern eine lokale Sicherung
durchführen (z. B. auf eine externe Festplatte), lässt man bei der Variable
BACKUPPATH
den Hostnamen weg.
#!/usr/bin/env bash
################################################################
#
# syncup
# Synrchonisiert die Backup-Daten
#
# Copyright 2009 Emanuel Duss
# Licensed under GNU General Public License
#
# 2009-12-07; Emanuel Duss; Erster Entwurf
# 2009-12-15; Emanuel Duss; Erste produktive Version
# 2010-01-17; Emanuel Duss; rsync --progress
# 2010-09-14; Emanuel Duss; $BACKUPSRV, prepare () für mount
# 2010-10-06; Emanuel Duss; rycnc -h (Human)
# 2010-11-25; Emanuel Duss; Nutze Parameter als Quellverzeichnis
# 2010-11-27; Emanuel Duss; Mehrere Verzeichnisse und Konfigfile
#
################################################################
################################################################
# Variabeln
TIMESTAMP="`date +%Y-%m-%d_%H-%M-%S`"
HOSTNAME="`uname -n`"
RSYNC="/usr/bin/rsync"
RSYNC_PARAMETER="-avhz --progress --delete"
BACKUPSRV="emanuel@eeebox"
BACKUPPATH="$BACKUPSRV:/media/backup/backup/backupdata/$HOSTNAME/"
CONFIGFILE="`dirname $0`/syncup.conf"
################################################################
# Main
# Lege die zu sichernden Files fest
if [ -n "$*" ]
then
SOURCE=`echo $* | awk '{ gsub("/ "," "); gsub("/$",""); print }'`
elif [ -e "$CONFIGFILE" ]
then
echo "Konfigurationsfile: $CONFIGFILE"
SOURCE=`grep -E "^[^#]" $CONFIGFILE | tr "\n" " " | awk '{ gsub("/ "," "); gsub("/$",""); print }'`
else
echo "Usage:"
echo "syncup [ Verzeichnisse und Dateien ]"
echo ""
echo "Wird kein Parameter angegeben, wird das Konfigfile $CONFIGFILE verwendet."
exit 1
fi
# Info ausgeben
echo
echo "Source: $SOURCE"
echo "Target: $BACKUPPATH"
echo
# Backup-HD mounten
ssh $BACKUPSRV "sudo mount /media/backup"
# Dateien synchronisieren
$RSYNC $RSYNC_PARAMETER $SOURCE $BACKUPPATH
# Backup-HD umounten
ssh $BACKUPSRV "sudo umount /media/backup"
# EOF
Entweder wird das Skript direkt mit ./syncup
im aktuellen Verzeichnis
aufgerufen, oder man platziert es in einen Ordner, der in der $PATH
-Variable
eingetragen ist (z. B. /usr/local/bin
). Jetzt kann dieses Skript in der
Konsole aufgerufen werden:
emanuel@discordia:~
$ sudo syncup Daten/ /etc/ /var/www
Source: /etc
Target: emanuel@eeebox:/media/backup/backup/backupdata/discordia/
sending incremental file list
etc/openvpn/client.conf
880 100% 175.78kB/s 0:00:00 (xfer#1, to-check=539/1389)
sent 47.16K bytes received 219 bytes 31.59K bytes/sec
total size is 6.02M speedup is 127.00
Ich muss das Skript mit den nötigen Rechten aufrufen. Das Verzeichnis /etc
ist
nur durch den User root
vollständig lesbar. Deshalb rief ich das Skript mit
sudo
auf. Für eigene Verzeichnisse ist dies nicht nötig.
Die Daten befinden sich jetzt im Ordner backupdata
auf dem Backup-Server.
Das File syncup.conf
sieht folgendermassen aus:
################################################################
#
# syncup.conf
# Konfigurationsdatei fuer syncup
#
# Copyright 2010 Emanuel Duss
# Licensed under GNU General Public License
#
# 2010-11-27; Emanuel Duss; Erste Version
#
################################################################
# Verzeichnisse
/home/emanuel/Daten
/home/emanuel/.config
/home/emanuel/.filezilla
/home/emanuel/.ssh
/home/emanuel/.vim
# Files
/home/emanuel/.conkyrc
/home/emanuel/.bashrc
/home/emanuel/.exrc
/home/emanuel/.fehrc
/home/emanuel/.history
/home/emanuel/.muttrc
/home/emanuel/.screenrc
/home/emanuel/.vimrc
/home/emanuel/.vimperatorrc
/home/emanuel/.xinitrc
/home/emanuel/.Xdefaults
/home/emanuel/.smbcredentials*
# Systemdaten
/etc
#EOF
Wenn syncup
ohne Parameter aufgerufen wird, werden alle Dateien und
Verzeichnisse aus diesem Konfigurationsfile gesichert:
emanuel@discordia:~
$ sudo syncup
Konfigurationsfile: /home/emanuel/Daten/Scripts/syncup.conf
Source: /home/emanuel/Daten /home/emanuel/.config /home/emanuel/.filezilla
/home/emanuel/.ssh /home/emanuel/.vim /home/emanuel/.conkyrc /home/emanuel/.bashrc
/home/emanuel/.exrc /home/emanuel/.fehrc /home/emanuel/.history /home/emanuel/.muttrc
/home/emanuel/.screenrc /home/emanuel/.vimrc /home/emanuel/.vimperatorrc
/home/emanuel/.xinitrc /home/emanuel/.Xdefaults /home/emanuel/.smbcredentials* /etc
Target: emanuel@eeebox:/media/backup/backup/backupdata/discordia/
sending incremental file list
etc/openvpn/up.sh
453 100% 0.00kB/s 0:00:00 (xfer#1, to-check=540/393538)
sent 6.34M bytes received 32.75K bytes 296.59K bytes/sec
total size is 73.20G speedup is 11479.75
Backup
Die Daten wurden erst auf den Server synchronisiert. Wenn man eine Datei auf der Workstation löschen würde, dann wäre diese bei der nächsten Synchronisation ebenfalls gelöscht. Darum erstelle ich pro Tag, Woche, Monat und Halbjahr eine Kopie aller Daten. Dies erledigt mein Backup-Server. Da ich hierfür Hardlinks verwende, wird bei jeder Kopie kein weiterer Speicherplatz beansprucht. Lediglich neue Daten beanspruchen neuen Speicherplatz. Das ist genial!
Das Backup-Skript sieht folgendermassen aus:
#!/bin/bash
################################################################
#
# backup
# Backup mit Hardlinks
#
# Copyright 2009 Emanuel Duss
# Licensed under GNU General Public License
#
# 2009-10-22; Emanuel Duss; Erster Entwurf
# 2009-12-05; Emanuel Duss; Erste produktive Version
# 2010-04-27; Emanuel Duss; Logfile in /var/log
#
################################################################
################################################################
# Variabeln
BACKUPDIR=/media/backup/backup
LOGFILE=/var/log/backup.log
TIMESTAMP=`date +%Y-%m-%d_%H-%M-%S`
################################################################
# Funktionen
usage ()
{
echo "Usage:
backup ( daily | weekly | monthly | yearly )"
}
################################################################
# Backup-Funktionen
daily ()
{
rm -r $BACKUPDIR/daily_7
mv $BACKUPDIR/daily_6 $BACKUPDIR/daily_7
mv $BACKUPDIR/daily_5 $BACKUPDIR/daily_6
mv $BACKUPDIR/daily_4 $BACKUPDIR/daily_5
mv $BACKUPDIR/daily_3 $BACKUPDIR/daily_4
mv $BACKUPDIR/daily_2 $BACKUPDIR/daily_3
mv $BACKUPDIR/daily_1 $BACKUPDIR/daily_2
mkdir $BACKUPDIR/daily_1
cp -al $BACKUPDIR/backupdata/* $BACKUPDIR/daily_1
}
weekly ()
{
rm -r $BACKUPDIR/weekly_4
mv $BACKUPDIR/weekly_3 $BACKUPDIR/weekly_4
mv $BACKUPDIR/weekly_2 $BACKUPDIR/weekly_3
mv $BACKUPDIR/weekly_1 $BACKUPDIR/weekly_2
mkdir $BACKUPDIR/weekly_1
cp -al $BACKUPDIR/backupdata/* $BACKUPDIR/weekly_1
}
monthly ()
{
rm -r $BACKUPDIR/monthly_12
mv $BACKUPDIR/monthly_11 $BACKUPDIR/monthly_12
mv $BACKUPDIR/monthly_10 $BACKUPDIR/monthly_11
mv $BACKUPDIR/monthly_9 $BACKUPDIR/monthly_10
mv $BACKUPDIR/monthly_8 $BACKUPDIR/monthly_9
mv $BACKUPDIR/monthly_7 $BACKUPDIR/monthly_8
mv $BACKUPDIR/monthly_6 $BACKUPDIR/monthly_7
mv $BACKUPDIR/monthly_5 $BACKUPDIR/monthly_6
mv $BACKUPDIR/monthly_4 $BACKUPDIR/monthly_5
mv $BACKUPDIR/monthly_3 $BACKUPDIR/monthly_4
mv $BACKUPDIR/monthly_2 $BACKUPDIR/monthly_3
mv $BACKUPDIR/monthly_1 $BACKUPDIR/monthly_2
mkdir $BACKUPDIR/monthly_1
cp -al $BACKUPDIR/backupdata/* $BACKUPDIR/monthly_1
}
yearly ()
{
rm -r $BACKUPDIR/yearly_5
mv $BACKUPDIR/yearly_4 $BACKUPDIR/yearly_5
mv $BACKUPDIR/yearly_3 $BACKUPDIR/yearly_4
mv $BACKUPDIR/yearly_2 $BACKUPDIR/yearly_3
mv $BACKUPDIR/yearly_1 $BACKUPDIR/yearly_2
mkdir $BACKUPDIR/yearly_1
cp -al $BACKUPDIR/backupdata/* $BACKUPDIR/yearly_1
}
################################################################
# Main
echo "$TIMESTAMP Backup $1 start" >> $LOGFILE 2>&1
case $1 in
daily|weekly|monthly|yearly)
mount /media/backup
$1 >> $LOGFILE 2>&1
umount /media/backup
;;
*)
usage
exit 1
;;
esac
echo "$TIMESTAMP Backup $1 done" >> $LOGFILE 2>&1
# EOF
Kurze Erklärung: Der älteste Ordner wird gelöscht. Dann werden alle um eins
verschoben. Das Herzstück vom ganzen Backup verbirgt sich hinter der Option -l
von cp
. Diese Option erstellt lediglich einen Hardlink von allen Dateien. Dies
ist das tolle daran. Bei der Kopie mit cp -al src dst
wird kein weiterer
Speicherplatz auf dem Speichermedium belegt!
Backups erstellen
In der Crontab, welche mit sudo crontab -e
aufgerufen wird, erstelle ich
folgende Einträge:
# Backup
# Backup daily; 1:30h
30 1 * * * /usr/local/bin/backup daily
# Backup weekly; Montag, 2:00h
0 2 * * 1 /usr/local/bin/backup weekly
# Backup monthly; 1. Tag 4:00h
0 4 1 * * /usr/local/bin/backup monthly
# Backup yearly; 31. Dezember 3:00h
0 3 31 12 * /usr/local/bin/backup yearly
Jetzt werden zu bestimmten Zeiten die vberschiedenen Backups durchgeführt. Natürlich kann man die Befehle auch von Hand ausführen. Jedoch vereinfachen die Cronjobs diese Aufgabe erheblich!
Überwachung
Im Logfile können wir uns über den Status informieren:
emanuel@eeebox:~
$ tail /var/log/backup.log
2010-11-25_23-31-55 Backup daily start
2010-11-25_23-31-55 Backup daily done
Ich sehe keine Fehlermeldung. Das Backup hat funktioniert!
Restore
Ein Backup ist ohne erfolgreichen Restore gar nichts wert! Das restoren ist sehr einfach. Man kann einfach den gewünschten Ordner oder die gewünschte Datei zurückkopieren. Man muss gar nichts beachten!
emanuel@eeebox:/media/backup/backup/weekly_2/discordia
$ scp -r Daten/ discordia:/tmp/
Schluss
Wenn man das Backup einmal eingerichtet hat, hat man eine sehr zuverlässige Lösung um seine Daten zu sichern. Ich rate jedem an, seine Daten regelmässig zu sichern und auch den Restore durchzuspielen! Das Logfile sollte regelmässig nach Fehlern durchsucht werden, um die Integrität aller Backup-Daten festzustellen.
Viel Spass mit euren Backups.