"Binding" für CPU Last und Co externer Server

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Oekel
Beiträge: 147
Registriert: 28. Aug 2021 10:34
Answers: 0

"Binding" für CPU Last und Co externer Server

Beitrag von Oekel »

Moin,

ich suche eine möglichst schlanke Möglichkeit (auf Seiten einiger "Server"), um Mittels exec-Binding oder ähnlichem die aktuelle CPU und Ram Auslastung abzufragen.

Ich meine damit NICHT die Auslastung von dem Rechner, auf dem OH selber läuft, sondern z.B. jene von 2-3 weiteren PIs.
Die KI schlägt mir etwas vor wie

Code: Alles auswählen

ps aux --sort=-%cpu | head -n 2 | tail -n 1 | awk '{print $3}'
+ einen einfachen Http-Server, auf dem dieses Script ausgeführt wird und mittels curl erreichbar ist.

Geht es vielleicht einfacher und flexibler?
Gezielte Ausgaben aus htop wären mein Ziel.

LG

Benutzeravatar
udo1toni
Beiträge: 14046
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

Re: "Binding" für CPU Last und Co externer Server

Beitrag von udo1toni »

Google ohne AI ;) brachte mich auf den Befehl mpstat. Dieser Befehl beherrscht auch das Ausgabeformat JSON.

Voraussetzung für eine saubere Umsetzung ist das automatische Login per Public/Private Key Verfahren.
Das Paket sysstat muss auf dem Zielsystem installiert sein.

Im Folgenden meine Vorgehensweise dazu:
  1. ssh Login auf dem openHAB System (als User openhabian oder anderer Admin-User)
  2. Von dort Login als User openhab (abgefragt wird hier das Passwort des Admin-Users, der schon angemeldet ist)

    Code: Alles auswählen

    sudo su - -s /bin/bash openhab
  3. Verzeichnis für Schlüsselpaar anlegen und mit korrekten Rechten versehen:

    Code: Alles auswählen

    mkdir .ssh
    chmod 700 .ssh
    
    und einmal mit ls -la prüfen, dass das Verzeichnis .ssh vorhanden ist, mit den Besitzrechten drwx------ openhab:openhab
  4. Mit dem Befehl

    Code: Alles auswählen

    ssh-keygen -t ed25519
    erzeugst Du ein Schlüsselpaar. Der Default Dateiname sollte /var/lib/openhab/.ssh/id_ed25519 sein, was ok ist.
    Keinesfalls ein Passwort vergeben, der Schlüssel soll ja zur automatischen Anmeldung verwendet werden.
    Anschließend gibt es im Verzeichnis .ssh zwei Dateien, id_ed25519 und id_ed25519.pub
  5. Nun loggst Du Dich am besten parallel auf dem Zielsystem ein und installierst sysstat:

    Code: Alles auswählen

    sudo apt install sysstat
    Außerdem legst dort einen User openhab an

    Code: Alles auswählen

    sudo adduser openhab
    Vergib für den User ein Passwort, damit Du anschließend den Public Key bequerm kopieren kannst
  6. Ist der User angelegt, wechselst Du wieder auf das openHAB-System und gibst als User openhab den Befehl

    Code: Alles auswählen

    ssh-copy-id -i .ssh/id_ed25519 <name-des-zielsystems>
    ein, wobei <name-des-zielsystems> der Hostname oder die IP ist.
    ssh-copy-id fragt, ob der Rechner in die Liste vertrauenswürdiger Systeme aufgenommen werden soll. Weiter fragt es nach dem Passwort, was Du nun einmalig eingeben musst.
Damit sind alle Vorbereitungen soweit abgeschlossen.
Nun kannst Du testen, ob Der Zugriff funktioniert:

Code: Alles auswählen

ssh <name-des-zielsystems> -i .ssh/openhab_ed25519  mpstat -o JSON
Und als Ergebnis solltest Du sowas zu sehen bekommen:

Code: Alles auswählen

{"sysstat": {
        "hosts": [
                {
                        "nodename": "server",
                        "sysname": "Linux",
                        "release": "6.5.13-1-pve",
                        "machine": "x86_64",
                        "number-of-cpus": 12,
                        "date": "03.03.2024",
                        "statistics": [
                                {
                                        "timestamp": "22:31:03",
                                        "cpu-load": [
                                                {"cpu": "all", "usr": 2.56, "nice": 0.00, "sys": 2.81, "iowait": 0.44, "irq": 0.00, "soft": 0.03, "steal": 0.00, "guest": 0.25, "gnice": 0.00, "idle": 93.91}
                                        ]
                                }
                        ]
                }
        ]
}}
Passt alles, kannst Du Dich vom openHAB-System abmelden und beim User openhab auf dem Zielsystem das Passwort entfernen, dazu solltest Du dort vermutlich als anderer User angemeldet sein

Code: Alles auswählen

sudo passwd -d openhab
Wenn ein User kein Passwort hat, kann man sich nicht mehr mit Passwort anmelden, die Anmeldung über den Private Key funktioniert hingegen weiterhin.

Nun ist der Rest sozusagen ein Spaziergang, also, fast...
  1. Installiere das exec Addon
  2. Installiere das JSONPath Addon
  3. Lege ein exec:command Thing an
  4. Gib als command die Zeile an, die Du schon oben erfolgreich getestet hast
  5. Falls Du den Befehl zyklisch ausführen willst: Dafür gibt es den Parameter interval.
  6. Die Befehlszeile muss identisch auch in der whitelist hinterlegt werden ($OPENHAB_CONF/misc/exec.whitelist)
  7. Lege ein Number Item an, welches die CPU-Last anzeigen soll
  8. Verlinke dieses Item mit dem String Channel output
  9. Richte im Link ein Profile ein (JSONPATH und als Pfad $.sysstat.hosts.statistics.cpu-load.idle
Ein Wermutstropfen folgt jetzt, der Wert Idle gibt, wie der Name vermuten lässt, an, wie viel der Prozessor sich langweilt. Jedoch wird auch mit anderen Befehlen gewöhnlich nicht die Last ausgegeben, sondern verschiedene Aspekte. Wenn Du aber die Idle Prozentzahl von 100 abziehst, hast Du die Last über alles. Diese Kalkulation sollte machbar sein. :)

Alternativ könnte man auch ein kleines Script schreiben und es als Profile aufrufen. Das Script könnte dann JSONPath nutzen und "in einem Aufwasch" auch gleich noch den Idle-Wert von 100 abziehen.

Infos über das RAM kannst Du auf ähnliche Weise mittels des Befehls free ermitteln. Leider beherrscht free nicht die Ausgabe über JSON.
Ob Du mit einem Schlüsselpaar arbeitest oder für jeden Rechner ein eigenes Schlüsselpaar erzeugst, bleibt Dir überlassen - sicherer sind mehrere Dateien, andererseits ist die Chance, dass ein einzelnes System korrumpiert wird und Du das mitbekommst und so verhindern kannst, dass sich ein Problem ausweitet, ohnehin eher theoretischer Natur :)
Du kannst den Public Key übrigens für beliebige Zielsysteme und beliebige User verwenden, allerdings ist dann das Kopieren des Public Key nicht mehr ganz so komfortabel. So oder so benötigst Du auf allen Zielsystemen mindestens normalen Zugriff, um den Befehl mpstat ausführen zu dürfen, und der Befehl muss installiert sein.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.2.2, LXC), mit openHABian eingerichtet

Oekel
Beiträge: 147
Registriert: 28. Aug 2021 10:34
Answers: 0

Re: "Binding" für CPU Last und Co externer Server

Beitrag von Oekel »

Wahnsinn, danke für die ausführliche Anleitung. Braucht etwas Zeit bis ich die Ruhe finde dies auszuprobieren....

Benutzeravatar
lenschith
Beiträge: 248
Registriert: 11. Dez 2020 22:36
Answers: 0

Re: "Binding" für CPU Last und Co externer Server

Beitrag von lenschith »

Ich mache das über einen cron job
https://community.openhab.org/t/show-sy ... r/106113/4

ich glaube top musste ich installieren

Systemcheck:

Code: Alles auswählen

#!/bin/bash

OHIP="xxx.xxx.xxx.xxx"

send(){
    curl -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "$state" "http://$OHIP:8080/rest/items/$item/state"
}

item="raspi11_SysInfo_CPU_Prozent"
state=$(top -bn 1 | awk '/%CPU/ && !/USER/{gsub(/,/, "."); printf "%.0f\n", $2}')
send

item="raspi11_SysInfo_CPUAuslastung_1min"
state=$(uptime | sed -n -e 's/.*average: //p' | sed 's/ /\n/g' | sed -n 1p | sed 's/.$//' | sed 's/,/\./' )
send

item="raspi11_SysInfo_CPUAuslastung_5min"
state=$(uptime | sed -n -e 's/.*average: //p' | sed 's/ /\n/g' | sed -n 2p | sed 's/.$//' | sed 's/,/\./' )
send

item="raspi11_SysInfo_CPUAuslastung_15min"
state=$(uptime | sed -n -e 's/.*average: //p' | sed 's/ /\n/g' | sed -n 3p | sed 's/.$//' | sed 's/,/\./' )
send

item="raspi11_SysInfo_RAM_total"
state=$(free -m | sed -n 2p | sed 's/ /\n/g' | sed -r '/^\s*$/d' | sed -n 2p)
send

item="raspi11_SysInfo_RAM_Frei"
state=$(free -m | sed -n 2p | sed 's/ /\n/g' | sed -r '/^\s*$/d' | sed -n 7p)
send

item="raspi11_SysInfo_RAM_Benutzt"
state=$(free -m | sed -n 2p | sed 's/ /\n/g' | sed -r '/^\s*$/d' | sed -n 3p)
send

item="raspi11_SysInfo_Speicher_total"
state=$(df -m | grep '/dev/root' | sed 's/ /\n/g' | sed -r '/^\s*$/d' | sed -n 2p)
send

item="raspi11_SysInfo_Speicher_Frei"
state=$(df -m | grep '/dev/root' | sed 's/ /\n/g' | sed -r '/^\s*$/d' | sed -n 4p)
send

item="raspi11_SysInfo_Speicher_Benutzt"
state=$(df -m | grep '/dev/root' | sed 's/ /\n/g' | sed -r '/^\s*$/d' | sed -n 3p)
send

item="raspi11_SysInfo_Threads"
state=$(ps -eLf | wc -l)
send
item="raspi11_SysInfo_Laufzeit"
state=$(less /proc/uptime | awk '{print $0/60;}'|  cut -d "," -f1 )
send

item="raspi11_SysInfo_Temperatur"
state=$(vcgencmd measure_temp | sed 's/temp=//' | sed "s/'C//" )
send
Updates:

Code: Alles auswählen

OHIP="xxx.xxx.xxx.xxx"

send(){
    curl -X PUT --header "Content-Type: text/plain" --header "Accept: application/json" -d "$state" "http://$OHIP:8080/rest/items/$item/state"
}


#Updates bestimmen
sudo apt list --upgradable 2>/dev/null | tail -n +2 >.alt
sudo apt update 1>/dev/null 2>/dev/null
sudo apt list --upgradable 2>/dev/null | tail -n +2 >.neu

diff=$(diff .neu .alt | grep "<" | sed 's/< //g')
anzahl=$(cat .neu | wc -l)


IFS=$'\n'                                                                                                                                                                       #Seperator auf Neuzeile setzen für for-loop
updates_names="Verfügbare Updates: $anzahl"



#Alte Updates einfügen, falls die Anzahl der alten Updates ungleich 0 ist
input=$(cat .alt )

if [ "$(cat .alt | wc -l)" -ne "0" ]; then
    updates_names="$updates_names  Bisher:}$(cat .alt | wc -l)"

    for line in $input
    do
        name=$(echo $line | cut -d"/" -f1)#Namen zuschneiden
        updates_names="$updates_names $name" #Namen konkatenieren
    done
fi



#Neue Updates einfügen
#Diff ist nie leer, da OH die Annotation nur einträgt, wenn sich die Anzahl geändert hat. Somit kann immer das "Neue" im String enthalten sein
updates_names="$updates_names  Neu:}$(( $(cat .neu | wc -l) - $(cat .alt | wc -l) ))"

for line in $diff
do
    name=$(echo $line | cut -d"/" -f1)#Namen zuschneiden
    updates_names="$updates_names $name" #Namen konkatenieren
done

updates_names=$(echo $updates_names | sed 's/ /\\n/g' ) #Leerzeichen durch "\n" ersetzen
updates_names=$(echo $updates_names | sed 's/\\n/ /' | sed 's/\\n/ /' | sed 's/\\n/ /' | sed 's/\\n/ /' ) #Die ersten e "\n" durch Leerzeichen ersetzten
updates_names=$(echo $updates_names | sed 's/}/ /' | sed 's/}/ /') #In Zeilen 30 und 36 wurde statt einem Leerzeichen eine "}" vewendet, dass dieses nicht durch ein "\n" ersetzt wird


#Aufräumen
rm .alt .neu


#Senden
item="raspi11_SysInfo_Updates_Namen"
state=$(echo $updates_names)
send

sleep 10

item="raspi11_SysInfo_Updates"
state=$anzahl
send


exit
Gruß Lenschi
openHAB4.1.2 in einem Docker Container auf RPI4b-4GB, AVM: Fritz!Box 7590 - DECT301 - Comet, DECT210, DECT200, DECT440, Alexa, Shelly, Tasmota, ESP Easy, WLED

Antworten