Viele Webhoster bieten eine Möglichkeit, einfache Backups zu erstellen oder diese sogar nach „extern“ per FTP wegzusichern. Dummerweise handelt es sich bei dieser Sicherung jedes mal um ein Fullbackup. Will sagen, in der Regel hat man genau einen Wiederherstellungspunkt für das Backup auf dem Webserver liegen. Oder eben alternativ viele Fullbackups auf einem FTP Server – wobei man hier ja auch noch aufpassen muss, dass die Backups sich nicht bei jedem Lauf überschreiben. Meistens heißen die Dateien ja doch alle gleich.
Wie schon im vorherigen Artikel beschrieben gehe ich bei der Sicherung wie folgt vor: per sshfs wird das Filesystem des Webservers lokal gemountet. Auf dem Webserver des Hosters läuft ein CRON-Job, der jede Minute ein Script auf dem Server startet. Das Script schaut zunächst in einem Verzeichniss nach einem Startflag (Datei). Wenn die Datei gefunden wurde dumpt es die gefüllten MySQL Datenbanken ins Filesystem und schreibt die Aktionen in ein Logfile. Auf dem Backupserver wird per CRON-Job das Backuptool backup2l gestartet. In der Config des Backuptools wird vor dem Backup ein Script gestartet, dass per sshfs das Dateisystem des Webservers mountet und das Startflag für den CRON-Job auf dem Webserver erzeugt. Nach einem Timeout von 5 Minuten wird geprüft ob das Datenbankbackup gelaufen ist und eine entsprechende Meldung ausgegeben. Anschließend läuft backup2l los und sichert per afio und gzip/bzip den Inhalt des Filesystems.
Was wird benötigt?
Auf dem Webserver:
- cron mit der Möglichkeit eigene Scripts laufen zu lassen
- Zugang per ssh/sftp (oder ftp/webdav)
- mysqldump
Auf dem Backupserver:
- sshfs (alternativ curlftpfs; unverschlüsselt)
- backup2l
- afio (alternativ tar)
- buffer
- gzip/bzip
Beginnen wir nun mit dem Webserver. Hier muss ein Cronjob eingerichtet werden, der in möglichst kurzen Abständen läuft:
*/1 * * * * /<Pfad zum Homeverzeihnis>/bin/backup_dbs.sh
Das Script muss ausführbar sein (chmod 750) und sieht bei mir so aus:
#!/bin/bash #Programm zum Sichern der MySQL Datenbanken #Patrick Wessel, 23.02.2009 #Konstanten WORK=/<Homeverzeichnis>/sqldump SQLUSER=dbuser SQLDATENBANK=sql_prefix_* DUMP=/usr/bin/mysqldump QUOTA=/usr/bin/quota TMP=/<Homeverzeichnis>/tmp TRIGGER=$TMP/backup_dbs.run LOCK=$TMP/backup_dbs.lock LOG=$WORK/backup_dbs.log RC=0 #Variablen DATE=`date '+%d-%m-%Y um %H:%M:%S'` DATE2=0 #Trigger pruefen [ -f $TRIGGER ] || exit 0 #Logfile anlegen touch $LOG #Lockfile pruefen [ -f $LOCK ] && echo "$DATE: Backupjob laueft bereits: $(ps -ef|grep -i backup_dbs.sh)" | tee -a $LOG && exit 1 [ -f $LOCK ] || echo $DATE > $LOCK echo " " | tee -a $LOG echo "________________________________________________________________________________" | tee -a $LOG echo "Starte Datenbankdump am $DATE" | tee -a $LOG echo " " [ -d $WORK ] || mkdir -p $WORK | tee -a $LOG cd $WORK for i in 1 2 3 4 5 do RC=0 echo "Datenbank $SQLDATENBANK$i" | tee -a $LOG $DUMP -u $SQLUSER -p<DB-User Passwort> $SQLDATENBANK$i > $SQLDATENBANK$i.sql 2> /dev/null RC=$? if [ "$RC" -gt 0 ] then if [ "$RC" -eq 2 ] then echo "Datenbank: $SQLDATENBANK$i existiert nicht" | tee -a $LOG rm $SQLDATENBANK$i.sql | tee -a $LOG else echo "Fehler beim Datenbank Dump, Returncode: $RC" | tee -a $LOG fi else echo "Datenbank: $SQLDATENBANK$i erfolgreich gedumpt." | tee -a $LOG echo "Datei: $(du -s $SQLDATENBANK$i.sql)" | tee -a $LOG fi echo " " | tee -a $LOG done echo " " | tee -a $LOG $QUOTA | tee -a $LOG #Lock/Trigger loeschen [ -f $LOCK ] && rm $LOCK [ -f $TRIGGER ] && rm $TRIGGER #Backupzeit fuer Script setzen DATE2=`date '+%H%M%S'` echo $DATE2 | tee -a $LOG exit 0
Das Scripts gibts natürlich auch zum Download
Die Ausgabe ist ein wenig formatiert. Das hat den Vorteil, dass der Output auch in einer Mail ordentlich lesbar ist. Cron verschickt in der Regel eine Email an den Webmaster (dich) mit dem Output der Cronjobs.
Fortsetzung folgt…