Stichwort ‘Backup’

Daten sichern mit rsync

Dienstag, 24. Februar 2009

Täglich sichert das Programm rsync automatisch neue und veränderte Dateien verschiedener Verzeichnisse auf eine externe Festplatte.

Wichtige Dateien, wie jene von Programmier-Projekten, überführe ich in eine Versions-Verwaltung, so benötige ich keine Backup-Versionen. Habe ich eine Datei gelöscht von den zu sichernden Verzeichnissen, wird diese von der externen Backup-Festplatte ebenfalls gelöscht: Auf der Backup-Festplatte sind Spiegel der gesicherten Verzeichnisse.

Zum Sichern schrieb ich ein Bash-Skript. Es liest aus einer Konfigurationsdatei die Namen der Quell- und Zielverzeichnisse und die Namen von Dateien mit Mustern von Dateien, die nicht gesichert werden sollen, beispielsweise Temporärverzeichnisse oder Cache-Verzeichnisse. Das Skript:

#!/bin/sh
#
# Author  : Elmar Baumann
# Date    : 2006/05/05
# Requires: rsync, Konfigurationsdatei $CONF
# Doc     : Synchronisiert Dateien auf ein externes Backupmedium
#
#           Aufruf ohne Parameter
#
###############################################################################

SCRIPT=$(basename $0)

# Mountpoint für externes Backupmedium
BACKUP_MOUNTPOINT=/mnt/backup

# Konfigurationsdatei
CONF=${HOME}/conf/backup-directories.conf

# Spalte in der Konfigurationsdatei mit Quellverzeichnissen
COLUMN_SOURCE=1

# Spalte in der Konfigurationsdatei mit Zielverzeichnissen
COLUMN_TARGET=2

# Spalte in der Konfigurationsdatei mit Exclude-Pattern-Dateien
COLUMN_EXCLUDE=3

# Logdatei
LOGFILE=${HOME}/log/${SCRIPT}.txt

# Zeilenumbruch als Fieldseparator
IFS="
"

# Optionen für rsync
RSYNC_OPTIONS="
--archive
--delete
--delete-excluded
"

###############################################################################

function print_date() {
    date +"%d.%m.%Y, %H:%M:%S Uhr"
}

function print_started() {
    echo "${SCRIPT}: $(print_date) Sichere Dateien auf '${BACKUP_MOUNTPOINT}'..." \
    | tee $LOGFILE
}

function print_finished() {
    echo "${SCRIPT}: $(print_date) Fertig. Logdatei: '${LOGFILE}'" \
    | tee -a $LOGFILE
}

function mount_backup_medium() {
    umount $BACKUP_MOUNTPOINT 2> /dev/null
    mount $BACKUP_MOUNTPOINT
    if [ $? != 0 ]
    then
        echo "${SCRIPT}: '${BACKUP_MOUNTPOINT}' laesst sich nicht einhaengen!" >&2
        exit 1
    fi
}

function umount_backup_medium() {
    sync
    umount $BACKUP_MOUNTPOINT
}

function trim() {
    echo $1 | sed -e 's/^ *//;s/ *$//'
}

function shrink_blanks {
    echo $1 | sed 's/  */ /g'
}

function get_column_of_line() {
    local line=$(shrink_blanks $1)
    local column=$2

    trim $(echo $line | cut -d " " -f $column)
}

function backup() {
    for line in $(cat $CONF | grep -v '^#.*')
    do
        source=$(get_column_of_line $line $COLUMN_SOURCE)
        target=$(get_column_of_line $line $COLUMN_TARGET)
        exclude=$(get_column_of_line $line $COLUMN_EXCLUDE)

        rsync $RSYNC_OPTIONS \
            --exclude-from=$exclude \
            $source \
            $target \
            2>&1 \
            | tee -a $LOGFILE
    done
}

###############################################################################

print_started
mount_backup_medium
backup
umount_backup_medium
print_finished

Die Konfigurationsdatei sieht so aus — zwischen den Verzeichnis- und Dateinamen stehen Leerzeichen:

# Quelle         Ziel                   Patterndatei für Ausschluss
#
/home/elmar      /mnt/backup/linuxhome  /home/elmar/conf/backup-exclude-patterns-home.conf
/mnt/bilder      /mnt/backup            /home/elmar/conf/backup-exclude-patterns-bilder.conf
/mnt/daten       /mnt/backup            /home/elmar/conf/backup-exclude-patterns-daten.conf
/mnt/doku        /mnt/backup            /home/elmar/conf/backup-exclude-patterns-doku.conf
/mnt/multimedia  /mnt/backup            /home/elmar/conf/backup-exclude-patterns-multimedia.conf

Ich lasse rsync nicht alle gesicherten Dateien ausgeben, in der langen Ausgabe übersähe ich Fehlermeldungen, beispielsweise Dateien, die nicht gelesen, geschrieben oder gelöscht werden können.

Die externe Backup-Festplatte ist nur während des Sicherns eingeschaltet, ich sollte nach dem Ausschalten die Kabel herausziehen, so beschädigt eine hohe Überspannung nicht die Festplatte.

Das Skript starte ich durch Aufruf, nicht automatisch beim Einschalten der Backup-Festplatte, diese könnte ich einschalten, veränderte oder gelöschte Dateien wieder herzustellen. Ich gebe den Alias ’s’ ein und drücke die Enter-Taste.

Jedes Jahr brenne ich die Daten auf zwei Sätze DVDs gleichen Inhalts und guter Qualität von verschiedenen Herstellern, aktuell einen Satz auf Verbatim Archival Grade, den anderen auf Plextor DVD+R, hergestellt von Taiyo Yuden. Der Brenner ist auf 4-fache Geschwindigkeit eingestellt anstelle 16-facher. Die DVDs beider Sätze stecken in Hängeregister-DVD-Hüllen lichtdichter Koffer, ein Satz lagert außer Haus. Die Dateinamen jeder DVD stehen auf der Festplatte in einer komprimierten Textdatei des gleichen Namens wie das DVD-Label.

Zum vollständigen Rücksichern sind im Skript die Variablen target und source zu vertauschen - vielleicht erweitere ich es um diese Option: Das Skript wird bei gesetzter Option Spalte 2 der Konfigurationsdatei für source auswählen und die Spalte 1 für target: COLUMN_SOURCE=2 und COLUMN_TARGET=1.

MySQL-Datenbanken wiederherstellen

Sonntag, 7. Dezember 2008

Im letzten Artikel beschrieb ich, wie ich meine MySQL-Datenbanken sichere mit dem Programm mysqldump. Für jede Sicherung gilt das Prinzip: Prüfe, ob die Sicherung in Ordnung ist!

Für MySQL-Datenbanken bedeutet das: Schreibe das Backup in eine andere MySQL-Datenbank und prüfe, ob der Inhalt in Ordnung ist. Einsgepielt wird eine mysqldump-Sicherung mit folgendem Befehl:

cat datenbank-Fri.sql.gz | gzip -d | mysql andere_datenbank

Im Beispiel schreibt das Programm mysql den Inhalt der Datenbank datenbank-Fri.sql.gz in die Datenbank andere_datenbank . datenbank-Fri.sql.gz wurde geschrieben von mysqldump und komprimiert mit gzip,

Bislang prüfte ich einmalig für eine Datenbank per Durchsicht: Ich konfigurierte beispielsweise das Weblog so, dass es die andere Datenbank benutzte. Anschließend rief ich ein paar Seiten auf und klickte auf ein paar Links. Wollte ich den Inhalt genau prüfen, würde ich ein Tool suchen oder schreiben, das die Tabellen und Inhalte zweier Datenbanken automatisch vergleicht und bei Abweichungen mich per E-Mail informiert.

Ob eine aufgespielte Sicherung nach Umzug auf einen anderen Webserver sofort funktioniert, hängt ab davon, wie das Weblog, Content Management-System oder Wiki URLs behandeln. WordPress beispielsweise schreibt in die Tabelle options den URL des Blogs in die Spalte option_value in die Zeilen, für die die Spalte option_name die Werte siteurl und home enthält. Dieser sollte überprüft und gegebenenfalls geändert werden. Das gleiche gilt für die Option upload_url_path.

MySQL-Datenbanken sichern

Mittwoch, 3. Dezember 2008

Etliche Weblogs, Wikis und Content Management-Systeme speichern den Inhalt - alles was ich schreibe - in MySQL-Datenbanken. MySQL-Datenbanken sind Dateien auf der Festplatte eines Webservers, diesen besitzt ein Internet-Dienstleister.

Spätestens nach einem Wechsel des Webservers will ich den Inhalt der alten Datenbanken einfügen in neue MySQL-Datenbanken mit wenig Aufwand.

Dazu sichere ich die Datenbanken des Webservers auf meinen lokalen Rechner. Weitere Gründe für die lokale Sicherung:

  1. Die Datenbank könnte beschädigt werden und nicht mehr (vollständig) wiederhergestellt
  2. Cracker und Schadsoftware könnten die Datenbank verändern
  3. Der Internet-Dienstleister könnte seinen Dienst einstellen ohne dass ich vorher meine Daten auf irgend eine Weise retten kann

In einem Artikel über die Prinzipien der Datensicherung schrieb ich, Backups sollen automatisch ablaufen. Bei mir sieht das so aus:

  1. Einmal täglich sichert auf dem Webserver das Programm mysqldump meine MySQL-Datenbanken mit den kompletten Einfügebefehlen
  2. Nach einer Woche wird die älteste Sicherung überschrieben, es existieren bis zu 7 Sicherungen, eine für jeden Wochentag
  3. Auf meinem lokalen Rechner ruft Cron täglich (automatisch) ein Skript auf; dieses veranlasst auf dem Webserver SQL-Dumps (1.) und speichert die SQL-Dumps auf die lokale Festplatte
  4. Inhalte, die das Weblog, Wiki, Content Management-System nur auf die Webserver-Festplatte speichern und nicht in die Datenbank, werden heruntergeladen und auf die lokale Festplatte gespeichert, sofern noch nicht geschehen oder diese auf dem Webserver modifiziert wurden
  5. Die Daten der lokalen Festplatte werden täglich auf eine externe Festplatte gesichert, die nur während der Sicherung eingeschaltet ist; wäre Geld kein Thema, würde ich die lokale Festplatte auf ein LTO 4-Streamerband sichern lassen

Der Webserver muss folgende Programme anbieten und auf irgend eine Weise ausführen lassen:

  • mysqldump
  • gzip, die Komprimierung von mysqldump könnte nicht funktionieren
  • mail

Dies berücksichtige ich bei der Auswahl eines Webservers.

Besser ist ein Webserver, bei dem ich zeitgesteuert Programme ausführen lassen kann, es reicht aber einer, der CGI-Skripte erlaubt, unter anderem Bash-Skripte, die sich für diese Aufgabe eignen.

Für den SQL-Dump schrieb ich zwei Bash-Skripte: Eines, das die Datenbank sichert und bei Fehlern eine E-Mail schickt und ein anderes, das für alle Datenbanken dieses Skript aufruft. Sie können beide herunterladen:

  1. Skript, das eine Datenbank sichert
  2. Skript, das für alle Datenbanken Skript 1 aufruft

Aus den Skripten löschte ich: Skript 1 verlangt ein Passwort, wird keines oder ein falsches überreicht, unternimmt es nichts und Skript 2 ruft Skript 1 mit einem Passwort auf.

Das Skript, das cron täglich aufruft auf meinem lokalen Rechner, ruft das CGI-Skript 2 auf mit dem Webbrowser lynx und dem Parameter --dump. Lynx zeigt die Skriptausgabe an und beendet sich, die Ausgabe wird umgeleitet in eine Logdatei.

Die Dateien, die im Dateisystem der Webserver-Festplatte gespeichert sind - die WordPress-, MediaWiki-, … -Installationsverzeichnisse - sowie die mysqldump-Backupdateien spiegelt das Perl-Skript mirror auf meine lokale Rechnerfestplatte (täglich aufgerufen durch cron). Es gibt weitere Programme, die Dateien eines Webservers spiegeln können, spontan fallen mir diese ein: wget und ncftp.