Datenbanken mit bareos sichern

Das Sichern von Datenbanken mit bareos oder bacula ohne dabei Plugins zu benutzen ist über Skripte möglich, die in der Jobdescription über den Parameter „RunBeforeJob“ eingebunden werden. Das hier beschrieben Vorgehen lässt sich auch auf andere Backupsoftware wie z.B. rsnapshot übertragen (hier können ebenfalls Skripte eingebunden werden).

Hintergrund

Ich stand vor dem Problem meine Datenbanken in mein Backup (mit bareos) einzubinden. Die Ergebnisse verschiedener Suchläufe im Internet schlugen Plugins vor. Für die zwei der von mir genutzten Datenbanken PostgreSQL und MySQL wäre das auch ein gangbarer Weg. Allerdings bedeutete das eine ganze Menge ausprobieren basteln und selber übersetzen. Da das ganze auch direkt in einem produktiven System zum Einsatz kommen sollte verwarf ich jedoch die Idee mit den Plugins – Zeitmangel zum Ausprobieren und das Fehlen von Testsystemen waren Gründe hierfür.

Also blieb mir nur die Möglichkeit ein Skript zu bauen und dieses über den Sicherungsjob aufzurufen.

Das Mittel der Wahl waren die Dumpbefehle der jeweiligen Datenbanken. Der Nachteil der bei dem Erzeugen von Dumps entsteht, ist dass jedes mal wenn ein Dump erzeugt wird (in meinem Fall sollen die bestehenden überschrieben werden) für das Backupprogramm die Datei geändert wurde (Zeitstempel). Dadurch werden auch jedes mal die Dumpdateien neu gesichert. Für die Zielmedien (Bänder oder Festplatten) ist das eher Kontraproduktiv.

Aus diesem Grund beschloss ich die Dumps permanent in einem bestimmten Verzeichnis vorzuhalten und die aktuellen Dumps in ein temporärem Verzeichnis anzulegen, die Dumps einer Datenbank im Backupverzeichnis (Bestand) mit dem im temporären Verzeichnis über das Programm „diff“ zu vergleichen und wenn sich eine Änderung ergibt den Dump aus dem temporären Verzeichnis in das Backupverzeichnis zu verschieben. Dadurch stelle ich sicher, dass nur veränderte Dumps ihren Weg auf die Backupmedien finden.

Hinweis

Das ganze ist eher interessant für kleine Datenbanken. Sollte sich die Datenbankgröße stark vergrößern sollte man auf eines der Plugins zurückgreifen.

Skript

Genug der Theorie, hier der Codeschnipsel des Bashskriptes:

#!/bin/bash

backupDir=/var/backup/databases
tmpDir=/tmp/databases

# Sicherstellen dass die beiden Zielverzeichnisse existieren, wenn nicht dann 
# neu erstellen

if [ ! -d $backupDir ]; then
    mkdir $backupDir
fi

if [ ! -d $tmpDir ]; then
    mkdir $tmpDir
fi

cd $tmpDir

# PostgreSQL

# Alle Datenbanke auflisten lassen und an die Liste an eine for_Schleife 
# übergeben
# Nachfolgende Befehl erfordert inen Eintrag in der
# /etc/sudoers

for DB in `sudo -H -i -u postgres psql -At -c "select datname from pg_database where not datistemplate and datallowconn order by datname;" postgres`
    do
        echo "createing dump: $DB"
                # Nachfolgende Befehl erfordert einen Eintrag in der
                # /etc/sudoers
        sudo -H -i -u postgres pg_dump -Fp $DB > $tmpDir/$DB.pgsql
        if [ -f $backupDir/$DB.pgsql ]; then
            echo "are there diffs between $DB in $tmpDir and $backupDir?"
            diff $tmpDir/$DB.pgsql $backupDir/$DB.pgsql > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                    echo "diffs found -> moving $tmpDir/DB.pgsql to $backupDir"
                mv $tmpDir/$DB.pgsql $backupDir/$DB.pgsql
            else
                    echo "No diffs found in the $DB-dumps"
            fi
        else
            echo "New databasedump -> moving to Backupdir"
            mv $tmpDir/$DB.pgsql $backupDir/$DB.pgsql
        fi
    done

# MySQL

TARGETHOST=your.host.tld
USER=yourDbUser
Password=yourDbUserPassword
DATABASENAME=nameOfYourDb

echo "Dump MySQL-db from $TARGEHOST"
mysqldump --skip-dump-date -h $TARGETHOST -u $USER -p$PASSWORD $DATABASENAME > $tmpDir/$DATABASENAME.mysql

echo "are ther diffs between $DATABASENAME in $tmpDir and $backupDir?"
diff $tmpDir/$DATABASENAME.mysql $backupDir/$DATABASENAME.mysql > /dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "diffs found -> moving to $backupDir"
        mv $tmpDir/$DATABASENAME.mysql $backupDir/$DATABASENAME.mysql
else
        echo "No differences found an Database $DATABASENAME"
fi

# temporäre Daten löschen
rm $tmpDir/*

Wichtig beim mysqldump ist der Schalter „–skip-dump-date“. Wird dieser Schalter weggelassen, schreibt der mysqldump am Ende des Dumps noch die Information wann der Dump erstellt wurde. Das hat zur Folge, dass sich die Dumps im temporären Verzeichnis und im Backupverzeichnis immer unterscheiden und die Dumps von der Backupsoftware immer mitgesichert werden, auch wenn sich die eigentlichen Daten des Dumps nicht verändert haben.

In der /etc/sudoers muss für das Backup der Postgresdatebank folgendes eingefügt werden, sofern nicht über einen eigenen Postgresbenutzer (eindeutig der bessere Weg) gearbeitet wird:

backupuser ALL=(postgres) NOPASSWD: /usr/bin/psql, /usr/bin/pg_dump

Die Idee Datenbankdumps von Postgres über sudo zu erzeugen kommt aus den Gegebenheiten von Debian.

Zugegeben das ist nicht gerade sicher aber zum Testen allemal OK ;-).

Einbinden in bareos

Ein Beispiel für einen Einfachen Job in bareos / bacula könnte wie folgt aussehen:

# Die Jobdefinition
Job {
  Name = "Backup Databases"
  JobDefs = "DefaultJob"
  FileSet = "Database Set"
  RunBeforeJob = "/path/to/script/db-bak.sh"
}
# ... und das dazugehörige Fileset
FileSet {
  Name = "Database Set"
    Include {
    Options {
      Signature = MD5
    }
    File = "/var/backup/databases"
  }
}

 Einbinden in rsnapshot

Das Einbinden in rsnapshot erfolgt auf noch einfachere Weise:

###
backup_script        /path/to/script/db-bak.sh        path/to/backupfiles
###