Am 15. Januar 2024 habe ich einen neuen
Raspi 4 B inklusive dem
empfohlenen offiziellen Netzteil erhalten und damit begonnen, die bisher
von einem Linux-PC gesteuerten Automationen zu Hause
(Stichwort SmartHome) auf diesen Raspi
zu migrieren.
Spätestens nachdem ich in einem Forum gelesen habe, dass ein Benutzer
während den Ferien erlebt hat, dass ein Netzteil seines Raspis ausgefallen
ist und in der Folge seine Steuerungen zu Hause (Jalousien,
Gartenbewässerung, etc.) komplett ausgefallen sind, beschloss ich, einen
Weg zur Hochverfügbarkeit der Home-Automation zu beschreiten.
Hier wird dieser Weg beschrieben.
Hardware
Am 21. Februar 2021 erhielt ich die neue Hardware:
- Raspberry Pi 4 8G Model B
- Official Raspberry Pi 4 Power Adapter USB-C Schwarz
- SanDisk Max Endurance 32GB
Erstmals wollte ich einen Raspi mit 8GB RAM ausprobieren und sicherheitshalber
bestellte ich das schwarze Netzteil (im Unterschied zum weissen Modell, welches
im Januar 2024 gekauft wurde); vielleicht erkaufe ich mir damit eine gewisse
Sicherheit, obwohl ich nicht weiss, ob das schwarze und weisse Netzteil bzgl.
Hardware wirklich unterschiedlich sind.
Als SD-Karte entschied ich mich für eine 'SanDisk Max Endurance' in der
Hoffnung, dass diese lange haltbar ist.
Installation des Raspberry Pi 4 B
Der neue Raspi wurde gleich eingerichtet wie derjenige vom
Januar 2024.
Positioniert wurde der neue Raspi diesmal nicht im Untergeschoss, sondern im
Obergeschoss, um eine örtliche Redundanz zu etablieren.
Zwei Rechner zu einem Hochverfügbarkeits-System verbinden
Die zwei Raspis haben die Namen raspi und raspi2. Anstatt nur via 'ping'
zu schauen, ob beide Rechner aktiv sind, wird regelmässig je ein
File auf den anderen Rechner kopiert. Falls dieser Vorgang nicht erfolgreich
ist, setzt sich der entspechende Rechner automatisch als MASTER.
Als crontab wird auf beiden Rechnern folgendes eingetragen:
*/2 * * * * $HOME/smarthome/HA/ha.sh >> $HOME/smarthome/HA/ha.log 2>>$HOME/smarthome/HA/ha.errlog
Das File 'ha.sh' sieht wie folgt aus:
Zur besseren Darstellung wurde vor dem Einfügen folgender Befehl benutzt:
cat ha.sh | > ha.text
Das HTML-File-Fragment 'ha_new.html' dient dazu, auf einer Webseite
den Status der beiden Rechner darzustellen. Ist z.B. der Rechner 'raspi'
nicht erreichbar/down, dann sieht dieses HTML-Fragment wie folgt aus:
Das File PRIMARY.MASTER hat folgenden Inhalt: PRIMARY_MASTER='raspi'
und ist auf beiden Rechnern identisch. Es dient dazu, zu definieren, welcher
der beiden Rechner der Master ist, falls beide Rechner online sind.
Das File MASTER.file wird durch das oben beschriebene Script ha.sh alle
zwei Minuten neu erstellt und sieht auf dem Master so aus:
MASTER='yes' SLAVE=raspi2
MASTER='no' SLAVE=raspi
Software auf den beiden Rechnern, die zum Hochverfügbarkeits-System
gehören
Die Software auf beiden Rechnern sollte generell identisch gehalten werden.
Dies kann z.B. nach einem Backup (siehe unten) auch mittels einem Script
überprüft werden.
Auf beiden Rechnern
wird ja alle zwei Minuten getestet, ob der andere ebenfalls funktioniert und
erreichbar ist. Dieser Status ist jeweils im File (siehe oben)
$HOME/smarthome/HA/MASTER.file gespeichert (MASTER='yes' oder
MASTER='no'). In allen Scripts auf beiden Rechnern lesen wir nun gleich zu
Beginn diesen Status wie folgt aus:
und können jeweils das via cron aufgerufene Script gleich beenden.source $HOME/smarthome/HA/MASTER.file if test "$MASTER" = "no" ; then echo "Not MASTER - exit! `date +%d.%m.%Y_%H:%M`" exit fi
Dies wurde genauso implementiert für die Steuerung der Storen bzw. Rollläden und ebenso für die automatisierte Gartenbewässerung inklusive der Sicherheitsüberwachung der Bewässerung, welche das Wasserventil schliesst, sollte es zu einer Zeit, wo keine Bewässerung vorgesehen ist, noch geöffnet sein.
Wichtig ist allerdings. dass die beiden redundanten Rechner stets auf dem aktuellen Stand der Daten sind. Wo immer in einem Script daher (auf dem MASTER) neue Daten generiert werden, wird sichergestellt, dass diese auf den SLAVE kopiert werden:
Damit ist sichergestellt, dass beide Maschinen zu jeder Zeit bezüglich der Daten auf dem gleichen Stand sind und im Falle eine 'Failovers', also des nahtlosen und automatischen Umschaltens auf das redundante System, die Arbeiten problemlos und quasi kontinuierlich mit aktuellen Daten weitergeführt werden können.scp -p -o ConnectTimeout=5 Daten.file $SLAVE:smarthome/Verzeichnis_auf_slave/
Backup der beiden redundanten Rechner
Ein Backup der selbst geschriebenen Software ist immer eine Notwendigkeit;
am besten immer dann, wenn die Software modifiziert wurde!
Aus diesem Grund habe ich auf einem dritten Rechner ein Verzeichnis
namens "RASPIsave" eingerichtet und dort folgendes Script gespeichert:
Mittels dem Befehl ./saveRASPIS_3.sh werden danach von beiden Raspis die jeweiligen Directories auf die Unterverzeichnisse raspi bzw. raspi2 kopiert - unter Beibehaltung der Daten und Rechte.#!/bin/bash # saveRASPIS_3.sh 24Feb2024/uk # Version für raspi3 # cd $HOME/RASPIsave USER=$LOGNAME # mkdir -p raspi mkdir -p raspi2 # machine=raspi #mkdir -p $machine/home rsync -avHx --exclude RASPIsave --delete $USER@$machine:/home/$USER $machine/home mkdir -p $machine/var/www/html rsync -avHx --delete $USER@$machine:/var/www/html/ $machine/var/www/html mkdir -p $machine/etc/network/if-up.d rsync -avHx --delete $USER@$machine:/etc/network/if-up.d/ $machine/etc/network/if-up.d mkdir -p $machine/usr/lib/cgi-bin rsync -avHx --delete $USER@$machine:/usr/lib/cgi-bin/ $machine/usr/lib/cgi-bin mkdir -p $machine/usr/local/bin rsync -avHx --delete $USER@$machine:/usr/local/bin/ $machine/usr/local/bin/ # machine=raspi2 #mkdir -p $machine/home rsync -avHx --exclude RASPIsave --delete $USER@$machine:/home/$USER $machine/home mkdir -p $machine/var/www/html rsync -avHx --delete $USER@$machine:/var/www/html/ $machine/var/www/html mkdir -p $machine/etc/network/if-up.d rsync -avHx --delete $USER@$machine:/etc/network/if-up.d/ $machine/etc/network/if-up.d mkdir -p $machine/usr/lib/cgi-bin rsync -avHx --delete $USER@$machine:/usr/lib/cgi-bin/ $machine/usr/lib/cgi-bin mkdir -p $machine/usr/local/bin rsync -avHx --delete $USER@$machine:/usr/local/bin/ $machine/usr/local/bin/ # cd /home/$USER/RASPIsave # # Find *errlog - Files grösser als Null: # echo " " echo "*errlog - Files grösser als Null von OCTAVE: " echo " " for file in `find ./ -name "*errlog" | grep octave` ; do if test -s $file ; then ll $file fi done # echo " " echo "*errlog - Files grösser als Null OHNE OCTAVE: " echo " " for file in `find ./ -name "*errlog" | grep -v octave` ; do if test -s $file ; then ll $file fi done #
Mittels dem Befehl ./differ.sh werden (in diesem Fall) in den Backups der beiden Rechner jeweils die Shell-Scripts (*.sh), die Octave-Scripts (*.m) sowie die Source-Codes (*.f) und die Executables (*.exe) - falls vergessen wurde, das Programm auf beiden Rechnern zu kompilieren bzw. das ausführbare Programm auf den anderen Rechner zu kopieren - der Fortran-Programme miteinander verglichen und bei Differenzen eine entsprechende Ausgabe gemacht.#!/bin/bash # differ.sh 22Mar2024/uk # cd $HOME/RASPIsave echo "Comparing *.sh Scripts:" for file in `find raspi/ -name "*.sh" | grep -v makeLink.sh | grep -v _alt | grep -v _new ` ; do for file2 in `find raspi2/ -name "*.sh" | grep -v makeLink.sh | grep -v _alt | grep -v _new` ; do fileA=`basename $file` fileB=`basename $file2` if test "$fileA" = "$fileB" ; then diff $file $file2 if test $? -ne 0 ; then echo "^^^$file" fi fi done done # echo "Comparing *.m Files:" for file in `find raspi/ -name "*.m" | grep -v _alt | grep -v _new ` ; do for file2 in `find raspi2/ -name "*.m" | grep -v _alt | grep -v _new` ; do fileA=`basename $file` fileB=`basename $file2` if test "$fileA" = "$fileB" ; then diff $file $file2 if test $? -ne 0 ; then echo "^^^$file" fi fi done done # echo "Comparing *.f Files:" for file in `find raspi/ -name "*.f" | grep -v _alt | grep -v _new ` ; do for file2 in `find raspi2/ -name "*.f" | grep -v _alt | grep -v _new` ; do fileA=`basename $file` fileB=`basename $file2` if test "$fileA" = "$fileB" ; then diff $file $file2 if test $? -ne 0 ; then echo "^^^$file" fi fi done done # echo "Comparing *.exe Files:" for file in `find raspi/ -name "*.exe" | grep -v _alt | grep -v _new ` ; do for file2 in `find raspi2/ -name "*.exe" | grep -v _alt | grep -v _new` ; do fileA=`basename $file` fileB=`basename $file2` if test "$fileA" = "$fileB" ; then diff $file $file2 if test $? -ne 0 ; then echo "^^^$file" fi fi done done #