Nach dem Umstieg von der Textfile basierten Konfiguration (fhem.cfg) auf die Datenbank basierte Konfiguration (configDB) wollte ich auch das gesamte Sicherungskonzept überarbeiten. Das einfache Backup durch FHEM ist hier nicht mehr ausreichend, da die Datenbanken nicht automatisch mit gesichert werden. Man muss dafür Sorge tragen, dass die Datenbank mit der Konfiguration und den Daten vor dem Backup gesichert werden. Deswegen auch der Hinweis "NOTE: make sure you have a database backup!" im Logbuch. Nach anfänglichen Versuchen dies mit FHEM Bordmitteln zu erledigen habe ich ein kleines Shellscript geschrieben welches das Backup anstelle des FHEM Backups übernimmt. Damit habe ich eine Anlaufstelle für das Backup und nicht alle überall verstreut. Voraussetzung dafür sind entsprechend eingerichtete Freigaben auf einem Backup-Datenträger.

Der Grundgedanke bei meinem Script ist, dass als erstes die angebundene Datenbank inkl. der Daten und der Konfiguration (configDB) in das Verzeichnis /opt/fhem/backup gesichert werden und danach das Backup erstellt wird. Das hat den Vorteil, dass mit dem Backup der kompletten FHEM Installation mittels "tar" die Daten der Datenbank gleich mit in eine gemeinsame Datei gesichert werden und somit die Versionsverwaltung übersichtlicher wird. Jedenfalls für mich.

Doch nun zum Script. Es ist in mehrere Teile Aufgebaut.

  1. Backup der Datenbank
  2. Löschen der nicht mehr benötigten Sicherungen
  3. Backup der FHEM Installation inkl. DB backup
  4. Auswertung und Rückgabe

Leider wurde das Backup mit einem Fehler beendet. Es gab eine Fehlermeldung "update was canceled. Please check manually!" obwohl das Backup ordnungsgemäß erstellt worden war. Ein Blick in die betreffende Zeile der 98_update.pm zeigte den Vergleich der laut Fehlermeldung fehlschlug. Das externe Script muss mindesten "backup done." zurückgeben. Mit der daraufhin zusätzlich eingeführten ERROR Variablen wird nun am Ende des Scriptes eine entsprechender Rückgabe generiert und das Update läuft auch erfolgreich durch.

2019.03.04 14:26:30.716 2: Backup with command: /usr/local/bin/FhemBackup.sh "configDB.conf" "./backup" "./CHANGED" "./configDB.conf" "./configDB.pm" "./contrib" "./demolog" "./docs" "./ebusd" "./FHEM" "./fhem.cfg" "./fhem.cfg.demo" "./fhem.pl" "./kindle" "./log" "./MAINTAINER.txt" "./README_DEMO.txt" "./restoreDir" "./unused" "./var" "./www"
2019.03.04 14:26:43.964 1: PERL WARNING: Use of uninitialized value $cmdret in pattern match (m//) at ./FHEM/98_update.pm line 256.
2019.03.04 14:26:43.965 1: PERL WARNING: Use of uninitialized value $cmdret in concatenation (.) or string at ./FHEM/98_update.pm line 257.
2019.03.04 14:26:43.968 1: Something went wrong during backup:
2019.03.04 14:26:43.970 1: update was canceled. Please check manually!

Ich habe das Script in /usr/local/bin gespeichert. Damit ist es von jedem Benutzer aus ohne Probleme zu starten.

#!/bin/bash

# Variablen vereinbaren
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/mnt/Syno/FHEM/backup"
BACKUP_NAME="FHEM-${DATE}.tar.gz"
SOURCE="/opt/fhem"
LOGFILE=$BACKUP_DIR/backup.log
ERROR=0

# Logbuch schreiben
echo "---------------------">>$LOGFILE
echo "${DATE} Start backup">>$LOGFILE

# Anzahl der Sicherungen die aufgehoben werden sollen
KEEP=10
BACKUPS=`find ${BACKUP_DIR} -name "FHEM-*.gz" | wc -l |sed 's/\ //g'`
while [ $BACKUPS -ge $KEEP ]
do
ls -tr1 ${BACKUP_DIR}/FHEM-*.gz | head -n 1 | xargs rm -f
BACKUPS=`expr $BACKUPS - 1`
done

# Backup der MySQL Datenbank
/usr/bin/mysqldump --user="sqldump" --password="<password>" --host="<SQL IP>" --port="<SQL Port>" fhem > /opt/fhem/backup/backupDB.sql
if [ "$?" -eq 0 ]
then
logger Backup DB success
date +"%Y%m%d_%H%M%S DB backup success">>$LOGFILE
else
logger Backup DB no success
date +"%Y%m%d_%H%M%S DB backup fail">>$LOGFILE
ERROR=$(($ERROR+1))
fi

# Gesamten FHEM Pfad in den den Sicherungsordener packen
tar -C "$SOURCE"/ . -zcvf "$BACKUP_DIR"/"$BACKUP_NAME" "$SOURCE" &>/dev/null
if [ "$?" -eq 0 ]
then
logger Backup FHEM success
date +"%Y%m%d_%H%M%S FHEM Backup success">>$LOGFILE
else
logger Backup FHEM no success
date +"%Y%m%d_%H%M%S FHEM Backup fail">>$LOGFILE
ERROR=$(($ERROR+1))
fi

# Rückgabe an FHEM und Logbuch schreiben
if [ "$ERROR" -eq 0 ]
then
echo "backup done."
date +"%Y%m%d_%H%M%S Backup done">>$LOGFILE
else
echo "backup fail."
date +"%Y%m%d_%H%M%S Backup fail">>$LOGFILE
fi

Mit dem fertigen Script kann man jetzt die entsprechenden Einstellungen in FHEM vornehmen. Im Device "global" muss das Script eingetragen werden und der Backup-Pfad benannt werden. Das ist in zweierlei Hinsicht wichtig. Durch die Angabe des Backup-Pfades wird jetzt durch das FHEM Backup auch der "/backup" Pfad gesichert. In diesem steht ja die Sicherung der Datenbank. Und die eigentliche Sicherung liegt nicht auf der gleichen Maschine sondern auf einem anderen Medium. Ein weiterer Vorteil dieser Methode ist, das der Befehl "backup" in FHEM weiter völlig transparent arbeitet, nur mit einem externen Script.

attr global backupcmd /usr/local/bin/FhemBackup.sh
attr global backupdir /mnt/Syno/FHEM-Test/backup

Gestartet wird das Backup von FHEM selbst mit einem einfache AT. 

defmod Backup at *23:55:00 backup

Ich lasse jeden Tag ein FHEM Backup anlegen und kopiere Dieses mit anderen Daten verschlüsselt auf mein 1TB Amazon Drive. Das erledigt die Synology Nachts wenn ich meine Internetleitung nicht brauche. Zusätzlich wird die Integrität der Sicherung 1x in der Woche geprüft

Kommentare powered by CComment