Ein Modul zur Erfassen von diversen RPi/Linux-Statistiken (SYSMON)

Begonnen von hexenmeister, 06 Dezember 2013, 17:44:38

Vorheriges Thema - Nächstes Thema

CoolTux


###############################################################################
#
# Developed with Kate
#
#  (c) 2019 Copyright: Marko Oldenburg (marko.oldenburg at araneaconsult dot de)
#  All rights reserved
#
#
#  This script is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  any later version.
#
#  The GNU General Public License can be found at
#  http://www.gnu.org/copyleft/gpl.html.
#  A copy is found in the textfile GPL.txt and important notices to the license
#  from the author is found in LICENSE.txt distributed with these scripts.
#
#  This script is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#
###############################################################################

use strict;
use warnings;
use POSIX;

use IO::Socket::INET;

##################################################
# Forward declarations
#
sub deconzDaemonSystemctl($$);
sub deconzDaemonState($);
sub sendStateToFHEM();
sub deconzDaemonCpuLast();

##################################################
# Variables:
my $self = {};
$self->{daemons} = ['deconz','deconz-wifi'];


###################################################
# Start the program
my ($arg,$debug,$acount);

return 'Usage status|restart' unless ( scalar(@ARGV) > 0 );
$arg = shift @ARGV;
$debug = 0;

if ( $arg eq 'restart' ) {
    deconzDaemonSystemctl('restart',$self->{daemons}->[0]);
    deconzDaemonSystemctl('stop',$self->{daemons}->[1]);
}

$acount = 0;
foreach ( @{ $self->{daemons} } ) {
    deconzDaemonState($self->{daemons}->[$acount]);
    $acount++;
}

deconzDaemonCpuLast() if ( $arg eq 'restart' or $arg eq 'status' );
       
sendStateToFHEM();


sub deconzDaemonSystemctl($$) {
    my ( $ctlCmd, $daemon ) = @_;
    system('systemctl ' . $ctlCmd . ' ' . $daemon);
    return 0;
}

sub deconzDaemonState($) {
    my $daemon = shift;
    $self->{daemons}->[$acount] = { daemon => $daemon };
   
    if ( open( STATE, "systemctl status $daemon 2>&1 |" ) ) {
        while ( my $line = <STATE> ) {
            chomp($line);
            print qq($line\n) if ( $debug == 1 );

            if ( $line =~ m#^\s+Loaded:\s(\S+)# ) {
                $self->{daemons}->[$acount]->{loaded} = $1;

            }
            elsif ( $line =~ m#^^\s+Active:\s(\S+\s\S+)\s\S+\s(\S+\s\S+\s\S+\s\S+);\s(\S+)# ) {
                $self->{daemons}->[$acount]->{active} = $1;
                $self->{daemons}->[$acount]->{timestamp} = $2;
                $self->{daemons}->[$acount]->{timeago} = $3;
            }
        }

        close(STATE);
    }
    else {
        die "Couldn't use STATE: $!\n";
        $self->{daemons}->[$acount]->{error} = 'Couldn\'t use STATE: ' . $;;
        return 1;
    }

    return 0;
}

sub deconzDaemonCpuLast() {

    if ( open( STATE, 'ps uax 2>&1 |' ) ) {
        while ( my $line = <STATE> ) {
            chomp($line);
            print qq($line\n) if ( $debug == 1 );

            if ( $line =~ m#^marko\s+\d+\s+(\d+.\d*).+\/usr\/bin\/deCONZ# ) {
                $self->{daemons}->[0]->{cpuLast} = $1;
            }
        }

        close(STATE);
    }
    else {
        die "Couldn't use STATE: $!\n";
        $self->{daemons}->[0]->{error} = 'Couldn\'t use STATE: ' . $;;
        return 1;
    }
   
    return 0;

}

sub sendStateToFHEM() {
    my $fhemDummy = 'dummyDeconzDaemonState';
   
    my $HOSTNAME = "p-fhem02.tuxnet.lan";
    my $HOSTPORT = "7072";
    my $socket = IO::Socket::INET->new('PeerAddr' => $HOSTNAME,'PeerPort' => $HOSTPORT,'Proto' => 'tcp')
        or die 'Cant\'t connect to FHEM Instance';

    $acount = 0;
    foreach ( @{ $self->{daemons} } ) {
        while ( my ( $r, $v ) = each %{$self->{daemons}->[$acount]} ) {
            print $socket 'setreading ' . $fhemDummy . ' ' . $self->{daemons}->[$acount]->{daemon} . '_' . $r . ' ' . $v ."\n" if ( $v ne $self->{daemons}->[$acount]->{daemon} );
            print $socket 'setreading ' . $fhemDummy . ' state ' . $v ."\n" if ( $r eq 'active' and $self->{daemons}->[$acount]->{daemon} eq 'deconz' );
        }
        $acount++;
    }
   
    $socket->close;
}


Hier mal ein kleines Beispielscript wie man Systemüberwachung an FHEM per Push senden kann.
Sieht in FHEM dann so aus.

Internals:
   FUUID      5c645655-f33f-b39c-204e-0043ce79d972bc47
   NAME       dummyDeconzDaemonState
   NR         64
   STATE      active (running)
   TYPE       dummy
   READINGS:
     2019-11-12 20:06:02   deconz-wifi_active active (running)
     2019-11-12 20:06:02   deconz-wifi_loaded loaded
     2019-11-12 20:06:02   deconz-wifi_timeago 4h
     2019-11-12 20:06:02   deconz-wifi_timestamp Tue 2019-11-12 15:21:30 CET
     2019-11-12 20:06:02   deconz_active   active (running)
     2019-11-12 20:06:02   deconz_cpuLast  4.1
     2019-11-12 20:06:02   deconz_loaded   loaded
     2019-11-12 20:06:02   deconz_timeago  6min
     2019-11-12 20:06:02   deconz_timestamp Tue 2019-11-12 19:59:04 CET
     2019-11-12 20:06:02   state           active (running)
Attributes:
   alias      deCONZ Service Status
   event-on-change-reading state,deconz-wifi_active,deconz_cpuLast,.*_timestamp
   group      deCONZ
   room       EDV
   setList    restart:noArg
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Wernieman

Arbeitest Du mit oder ohne Passwort?
Und wenn ich es richtig sehe, pures "telnet" ohne ssl?
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

CoolTux

Ohne Passwort und ohne SSL. Ist eine abgeschirmte Server VLAN Umgebung.
Kann man aber ohne weiteres an passen. Sollte nur als Inspiration dienen.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

Wernieman

Können wir bezüglich "Daten zu FHEM pusche" einen neuen thread aufmachen?

Dann würde ich auch mal meine "Lösung" reinstellen ...
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

CoolTux

Zitat von: Wernieman am 30 Januar 2020, 12:03:19
Können wir bezüglich "Daten zu FHEM pusche" einen neuen thread aufmachen?

Dann würde ich auch mal meine "Lösung" reinstellen ...

https://forum.fhem.de/index.php/topic,107924.0.html
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

choetzu

Zitat von: hexenmeister am 30 Januar 2020, 10:51:32
Ja, SYSMON löscht alle Reading. Es war gedacht, dass es keine 'alte' Einträge stehen bleiben sollen. Heute sehe ich diese Holzhammermethode auch als etwas "zu invasiv". Mit dem Attribut "user-fn" (s. Commandref f. SYSMON) sollte sich dein Vorhaben trotzdem implementieren lassen.

danke.. schön, dass es einen Weg gibt... leider vermutlich eine Stufe zu hoch für mich.. Ich kann den Commandref nicht wirklich entziffern. Und copy-paste geht nicht ;)

load:loadavg:.* { (split('\s',ReadingsVal($name,"loadavg","0")))[0] }

Commandref
user-fn <fn_name>:<Interval_Minutes>:<reading_name1>:<reading_name2>...[:<reading_nameX>],...
Liste der benutzerdefinierten Perlfunktionen.
Als <fn_name> können entweder Name einer Perlfunktion oder ein Perlausdruck verwendet werden. Die Perlfunktion bekommt den Device-Hash als Übergabeparameter und muss ein Array mit Werte liefern. Diese Werte werden entsprechend den Parameter <reading_nameX> in Readings übernommen.
Ein Perlausdruck muss in geschweifte Klammer eingeschlossen werden und kann folgende Paramter verwenden: $HASH (Device-Hash) und $NAME (Device-Name). Rückgabe wird analog einer Perlfunktion erwartet.
Wichtig! Die Trennung zwischen mehreren Benutzerfunktionen muss mit einem Komma UND einem Leerzeichen erfolgen! Innerhalb der Funktiondefinition dürfen Kommas nicht durch Leerzeichen gefolgt werden.
Raspi3, EnOcean, Zwave, Homematic

hexenmeister

ohne ausprobiert zu haben (kein FHEM zur Hand):

attr ... user-fn {(split('\s',ReadingsVal($NAME,"loadavg","0")))}:1:load

Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

choetzu

Zitat von: hexenmeister am 30 Januar 2020, 16:43:26
ohne ausprobiert zu haben (kein FHEM zur Hand):

attr ... user-fn {(split('\s',ReadingsVal($NAME,"loadavg","0")))}:1:load

super, danke. Es klappt zu 90% ;)

Wenn ich die Readings anschaue und sich Sysmon aktualisiert, dann übernimmt das usr-fn Reading load immer den letzten und nicht aktuellen Wert.


load 1.09 2020-01-30 16:55:38
loadavg 1.12 0.83 0.44

loadavg hatte vor der letzten Aktualisierung 1.09..  Ist zwar nicht schlimm, da sich die Angaben flott aktualisieren, aber es stimmt halt einfach nicht ;)

Weiter kommt im Logfile folgender Eintrag:
2020.01.30 16:57:38 3:  SYSMON Sysmon: getUserDefinedFn.1542 User-Function [{(split('\s',ReadingsVal($NAME,"loadavg","0")))}]: expected readings: [1], provided [3]
2020.01.30 16:58:38 3:  SYSMON Sysmon: getUserDefinedFn.1542 User-Function [{(split('\s',ReadingsVal($NAME,"loadavg","0")))}]: expected readings: [1], provided [3]

Soll ich das ignorieren und Verbose auf 2 stellen?
Raspi3, EnOcean, Zwave, Homematic

hexenmeister

Gegen Log Meldungen kannst versuchen wieder
  • einzubauen oder zusätzliche Readings hinzugügen: ... :load:load2:load3
    Oder du kommentiertst eine Zeile (1088) im Modul 42_SYSMON.pm aus:
    Zitat
      # Nicht mehr benoetigte Readings loeschen
      #my $omap = SYSMON_getObsoleteReadingsMap($hash);
    Danach kannst du mit gewöhnlichen User-Definied-Readings arbeiten, SYSMON löscht dann nichts mehr ungefragt.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Elektrolurch

Hallo,

ich habe jetzt mein System von einem Cubieboard 2 auf einen ODROID H2 mit Intel CPU und Buster portiert.
Leider geht das SYSMON - Modul nicht mehr. Ok, heit ja auch für die "Erfassung von RPI....
Es kommen keine readings mehr.
Am Beispiel der CPU - Frequenz bin ich mal durch den Code gegangen.
Da werden ja die Werte aus /sys/devices/system/cpu/cpu0... gelesen.
Habe das hier mal mit dem ODROID verglichen, da werden die beiden Kerne mit cpu1 und cpu3 adressiert.
Vermutlich liegt darin das Problem. Im code habe ich gesehen:

$cpuNum = 0 unless defined $cpuNum;
 
my $val;
  if(open(my $fh, '<', "/sys/devices/system/cpu/cpu".$cpuNum."/cpufreq/scaling_cur_freq")) {
    $val = <$fh>;
    close($fh);
  }


Man müsste wohl dem Modul irgendwie beibringen, das auf dem ODROID die CPUs 1 und 3 heißen.

Ließe sich das irgendwie bewerkstellingen?

Oder gibt es eine andere Lösung?

Gruß

Elektrolurch
 
configDB und Windows befreite Zone!

mumpitzstuff

Schau mal unter #1669. Die Daten zu pushen ist die bessere Lösung, da kannst du dir dann auch alles schön zusammen basteln...

Elektrolurch

Hallo Mumpitzstuff,
danke für den Hinweis. Das wäre ja ein neues Projekt.
Zunächst einmal suche ich eine Antwort auf meine Frage.

Elektrolurch
configDB und Windows befreite Zone!

der-Lolo

Hat schon jemand Sysmon auf dem Raspi4 im Einsatz? Im speziellem läuft FHEM in der offiziellen Docker Umgebung. Kann ich von der Docker Umgebung aus den Host überwachen? Was muss bei der Config beachtet werden..?

Ich hoffe ihr versteht meine gedankengänge und könnt mir ein bisschen auf die Sprünge helfen.

Danke vorab!

kadettilac89



Zitat von: der-Lolo am 03 März 2020, 09:53:37


Ich hoffe ihr versteht meine gedankengänge und könnt mir ein bisschen auf die Sprünge helfen.

Danke vorab!

Du willst den docker host überwachen. Sysmon bietet ssh-verbindung an. Der host ist als alias schon definiert. Heißt  Host.docker.internal.

du musst dir nur ssh key einrichten ... ich glaub in der Doku steht da auch was.

Def würde dann so aussehen...
ssh:<fhemusr>@host.docker.internal:22

kadettilac89

Zitat von: kadettilac89 am 11 Januar 2020, 18:25:47
Hi,

mir ist aufgefallen dass ich im Container kein Alias für gateway.docker.internal + host.docker.internal in /etc/hosts habe.

Wenn ich /entry.sh ausführe erhalte ich diese Ausgabe

ab Zeile 414 wird gateway.docker.intern
ab Zeile 421 wird host.docker.intern   angelegt.

Nachtrag zu meinem Post... die alias wurden im jan. Nicht eingetragen. Wenn der host nicht erreichbar ist dann fehlt das ggf. Auch bei dir