Dienstag, 30. Juli 2019

Definitionen in FHEM komplett umziehen

Ich habe mehrere System auf denen ich etwas teste und manchmal schleicht sich nach langer Zeit quasi "produktiver Betrieb" ein. Dann möchte ich gern die getestete Definition und alles was dazu gehört: Log, Logdateien, Plots usw. in das produktive System übernehmen. Da steht also die Aufgabe neben der eigentlichen Definition auch noch ein paar Dateien zu übernehmen. Ich habe mir dazu folgendes Vorgehen ausgedacht:
  1. Alle Dateien auf das Zielsystem kopieren oder das Quellsystem mounten
  2. Die wirklich benötigten Dateien an die richtige Stellen, mit den richtigen Berechtigungen, anhand der Definitionen in den FHEM Ordner kopieren.
  3. Die Definitionen vom Quell- auf das Zielsystem kopieren.
Dabei soll so viel wie möglich "automatisch" laufen. Damit ich wenig installieren und konfigurieren muss, hole ich alle potentiellen Dateien mit scp einfach pauschal lokal in ein temporäres Verzeichnis. Hat man große log Dateien - kann man auch einschränken.
host1='Hostname Instanz1'                        #Quell FHEM Instanz
tDir=fhem                                        #relativer Pfad der im lokalen Pfad (HomeDir des Users) angelegt und verwendet wird
mkdir -p $tDir/www
scp -r pi@$host1:/opt/fhem/log/ $tDir/           #kopiert den Remote Pfad log/ nach fhem/log/  
scp -r pi@$host1:/opt/fhem/www/gplot/ $tDir/www/ #kopiert den Remote Pfad www/gplot/ nach fhem/www/gplot/
Jetzt werden die wirklich notwendigen Dateien anhand der Definitionen ermittelt und lokal an die richtige Stelle mit den richtigen Berechtigungen kopiert. Ich mache das deshalb über FHEM.
Zu allen Schritten brauche ich meinen HTTP Client
wget -O fhemcl.sh https://raw.githubusercontent.com/heinz-otto/fhemcl/master/fhemcl.sh

Um die Einzeiler etwas übersichtlicher zu halten, definiere ich noch ein paar Variablen zu Beginn, $host1 und $tDir wurden im Befehlsblock oben schon definiert. In den Einzeilern wird einfach davon ausgegangen, dass der lokale Zugriff nur die Port Nummer 8083 erfordert.
inst1=$host1:8083                #URL Remote Instanz [http://[<user:password@>][<hostName>:]]<portNummer> 
rDir=$(pwd)/$tDir/               #absoluter Pfad für die (kopierten) Quelldateien
gDir='./www/gplot/'              #Pfad in dem die gplot Datei in FHEM liegen
devSpec='FILTER=NAME=.*Sensor.*' #wird in den Befehlen um TYPE= ergänzt
Man kann selbstverständlich die Quelldateien remote mit mount einbinden (z.B. nfs). Dann enthält $rDir den gemounteten Pfad.

Achtung: Die Einzeiler enthalten keine Fehlerbehandlung! Es kann also zu unvorhergesehenen Auswirkungen kommen!
Datensicherung!
Die Kopiervorgänge werden eventuell nicht oder falsch ausgeführt, können aber gleichnamige Dateien überschreiben! Die Änderungen in der cfg werden nicht automatisch gesichert, ein restart von FHEM stellt den alten Zustand wieder her.
Die devSpec sollte man im Zweifel immer testen!
bash fhemcl.sh $inst1 "list TYPE=.*:$devSpec"
Man sollte auch immer zunächst die Einzeiler ohne den letzten Ausführungsteil zur Probe laufen lassen!

Einzelne Schritte

Zunächst als "Fingerübung" die Grundlagen um aus bestimmten Definitionen, die "Sensor" im Namen haben, die Dateien zu kopieren.
  • der list Befehl erzeugt eine Tabelle aus Name und dem entsprechenden INTERNAL, von dieser wird nur die zweite Spalte benötigt,
    • für die log Datei wird mit sed alle Platzhalter %Y,%m usw. durch * ersetzt. Damit werden alle vorhandenen Log Dateien erfasst. 
    • für die gplot Datei wird mit sed noch $gDir vorangestellt und ".gplot" angehängt, 
  • der zweite sed Befehl ersetzt ./ durch den absoluten Pfad $rDir
    • Der Ausdruck ${rDir////\\/} erzeugt dabei aus dem normalen Pfadnamen einen "escaped" Pfadnamen: ersetzt also / durch \/.
  • Der tr Befehl am Ende macht aus der Zeilen- eine Leerzeichen getrennte Liste für den cp Befehl.

Die FileLog (log) Dateien

datei=$(bash fhemcl.sh $inst1 "list TYPE=FileLog:$devSpec logfile"|awk '{print $2}'|sed "s/%./*/g"|sed "s/.\//${rDir////\\/}/"|tr '\n' ' ')
bash fhemcl.sh 8083 "\"cp -n $datei ./log/\""

Die SVG (gplot) Dateien

datei=$(bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec GPLOTFILE"|awk '{print $2}'|sed "s/^/${gDir////\\/}/;s/$/.gplot/"|sed "s/.\//${rDir////\\/}/"|tr '\n' ' ')
bash fhemcl.sh 8083 "{qx(cp -n $datei ./www/gplot/)}"
Ich verwende bewusst zwei unterschiedliche Kopierbefehle. Die erste Variante blockiert das lokale FHEM nicht, allerdings hat man keine Rückmeldung wann der Kopiervorgang beendet ist. Die zweite Variante blockiert FHEM, was bei den kleinen gplot Dateien aber nicht stören sollte.

Definition

Jetzt brauchen nur noch die Definitionen auf das lokale Zielsystem kopiert werden.
bash fhemcl.sh $inst1 "list -r TYPE=FileLog:$devSpec"|bash fhemcl.sh 8083
bash fhemcl.sh $inst1 "list -r TYPE=SVG:$devSpec"|bash fhemcl.sh 8083

Verbundene Definitionen

Der list Befehl ist sehr vielseitig! Neben Gruppen von Definitionen kann man auch einzelne Geräte und deren komplette verbundenen Definitionen umziehen.
Achtung: "-R" funktioniert so richtig nur mit Device Namen ohne regExp, "-R" ist laut Doku auch "unvollkommen"!
So wird die SVG zusammen mit der zugehörigen FileLog Instanz übertragen.
bash fhemcl.sh $inst1 "list -R SVG_FileLog_SensorWG_1"|bash fhemcl.sh 8083

Abhängigkeit

Die SVG Definition und deren Funktion ist von der zugehörigen FileLog Definition abhängig. Also kann man von der SVG Definition alles notwendige ableiten. Die log Dateien anhand des SVG kopieren:
bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec LOGDEVICE"|sed 's/^.*\s/list /;s/$/ logfile/'|bash fhemcl.sh $inst1|awk '{print $2}'
Der Vorgang ist zweistufig, erst wird das LOGDEVICE aus der SVG Definition gelesen, daraus wieder ein list Befehl erzeugt und damit das log File direkt aus der Definition ausgelesen.
Nach dem obigen Schema kann man daraus die Dateiliste erstellen.
|sed "s/%./*/g"|sed "s/.\//${rDir////\\/}/"|tr '\n' ' '
Anstatt über eine Variable ($datei) kann man die Pipe auch fortführen.
|echo "\"cp -n $(cat -) ./log/\""|bash fhemcl.sh 8083
Der komplette Einzeiler ist wirklich lang.
bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec LOGDEVICE"|sed 's/^.*\s/list /;s/$/ logfile/'|bash fhemcl.sh $inst1|awk '{print $2}'|sed "s/%./*/g"|sed "s/.\//${rDir////\\/}/"|tr '\n' ' '|echo "\"cp -n $(cat -) ./log/\""|bash fhemcl.sh 8083

Um den list -R Befehl mit einer devSpec zu verwenden, muss man diese quasi erst auflösen.
Achtung: Wenn die devSpec nur eine Definition trifft, schlägt dieser einfache Einzeiler fehl!
bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec"|sed 's/^/list -R /'|bash fhemcl.sh $inst1|bash fhemcl.sh 8083

Finale

Damit hat man 3 Schritte ausgehend von einer devSpec:
  1. gplot Dateien kopieren
  2. log Dateien kopieren
  3. SVG Definitionen und die zugehörigen FileLog Definitionen übertragen.

bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec GPLOTFILE"|awk '{print $2}'|sed "s/^/${gDir////\\/}/;s/$/.gplot/"|sed "s/.\//${rDir////\\/}/"|tr '\n' ' '|echo "\"cp -n $(cat -) ./www/gplot/\""|bash fhemcl.sh 8083
bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec LOGDEVICE"|sed 's/^.*\s/list /;s/$/ logfile/'|bash fhemcl.sh $inst1|awk '{print $2}'|sed "s/%./*/g"|sed "s/.\//${rDir////\\/}/"|tr '\n' ' '|echo "\"cp -n $(cat -) ./log/\""|bash fhemcl.sh 8083
bash fhemcl.sh $inst1 "list TYPE=SVG:$devSpec"|sed 's/^/list -R /'|bash fhemcl.sh $inst1|bash fhemcl.sh 8083


Keine Kommentare:

Kommentar veröffentlichen