FHEM Forum

FHEM => Sonstiges => Thema gestartet von: supernova1963 am 03 Juni 2017, 18:06:20

Titel: In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 18:06:20
Mein Versuch mit ein Perl-Skript mit init.d automatisch zu starten droht zu scheitern.
Starte ich das Perl-Skript von der Befehlszeile mit einem '&' läuft alles einwandfrei:
fhem@FHEMDEV:~$ /opt/fhem/www/fing/fingService.pl &
[1] 5039
fhem@FHEMDEV:~$ pgrep -f fingService.pl
5039
fhem@FHEMDEV:~$ pidof fingService.pl
fhem@FHEMDEV:~$ pidof fingService
fhem@FHEMDEV:~$

top - 17:50:17 up 38 min,  3 users,  load average: 0,05, 0,03, 0,01
Tasks: 142 gesamt,   1 laufend, 141 schlafend,   0 gestoppt,   0 Zombie
%CPU(s):  0,2 be,  0,3 sy,  0,0 ni, 99,5 un,  0,0 wa,  0,0 hi,  0,0 si,  0,0 st
KiB Spch :  2041468 gesamt,  1511072 frei,   224476 belegt,   305920 Puff/Cache
KiB Swap:  2097148 gesamt,  2097148 frei,        0 belegt.  1662724 verfü Spch

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     ZEIT+ BEFEHL     
2234 root      20   0       0      0      0 S   0,0  0,0   0:00.03 kworker/u6+
2235 root      20   0  101448   6856   5872 S   0,0  0,3   0:00.01 sshd       
2285 fhem      20   0  101448   3592   2612 S   0,0  0,2   0:00.09 sshd       
2286 fhem      20   0   24288   5248   3388 S   0,0  0,3   0:00.03 bash       
2292 fhem      20   0   48656  14348   4640 S   0,0  0,7   0:00.08 fingServic+
2293 root      20   0   60760   4176   3680 S   0,0  0,2   0:00.00 sudo       
2294 root      20   0    4496    708    632 S   0,0  0,0   0:00.00 fing       

fhem@FHEMDEV:~$ pidof fing
fhem@FHEMDEV:~$ pgrep -f fingService
2292
fhem@FHEMDEV:~$ pgrep -f fing
2292
2293
2294
2295

Da es vom Verhalten ähnlich, wie homebridge im Hintergrund arbeiten soll, habe ich das zugehörige init.d Skript als Muster für meine Versuche genommen. Das erste Problem ergab sich bereits in der Code-Zeile PID = `pidof fingService`. Ich habe es auch im Terminal nicht hinbekommen mit pidof die PID zu ermitteln (s.o.). obwohl pgrep die korrekt PID anzeigt, wenn es im Terminal gestartet wurde. Deswegen habe ich 'pidof' durch pgrep ersetzt, in der Hoffnung das der weitere Code dann korrekt funktioniert,  leider vergebens. Es wird scheinbar willkürlich eine PID ermittelt, was dazu führt, dass der eigentliche start-Befehl nicht ausgeführt wird.

1. Wie stelle ich sicher, dass die korrekte PID ermittelt wird?
2. Wie muss der korrekte Startbefehl aussehen (die Umleitungen für homebridge sind meiner Ansicht nach nicht notwendig)?

Vielen Dank

Gernot


Nicht korrekt funktionierender /etc/init.d/fingService
#!/bin/sh

### BEGIN INIT INFO
# Provides: fingService
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $syslog $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time for fingService
# Description: Enable service provided by daemon.
### END INIT INFO
export PATH=$PATH:/usr/local/bin
export NODE_PATH=$NODE_PATH:/usr/local/lib/node_modules

PID=`pgrep -f fingService`
fingUser="fhem"
fhemHost=127.0.0.1          #FHEM Server (Masterinstanz)
fhemHostTelnetPort=7072     #TelnetPort der FHEM Instanz
fhemDefine="nc_init"

case "$1" in
start)
if ps -p $PID > /dev/null 2>&1; then
        echo "fingService is already running"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "setreading $fhemDefine info fingService is already running"
else
        #su - $fingUser -c "/opt/fhem/www/fing/fingService.pl > /dev/null 2>&1 &"
        su - $fingUser -c "/opt/fhem/www/fing/fingService.pl &"
        echo "fingService starting"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "setreading $fhemDefine info fingService starting"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "set $fhemDefine on"
        sleep 2
    $0 status
fi
;;
stop)
if ! ps -p $PID > /dev/null 2>&1; then
        echo "fingService is not running"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "setreading $fhemDefine info fingService is not running"
else
        kill $PID
        echo "fingSercive stopping"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "setreading $fhemDefine info fingService stopping"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "set $fhemDefine off"
        sleep 2
    $0 status
fi
;;
restart)
if ! ps -p $PID > /dev/null 2>&1; then
        $0 start
else
        $0 stop
        $0 start
fi
;;
status)
if ps -p $PID > /dev/null 2>&1; then
        echo "fingService is running PID $PID"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "setreading $fhemDefine info fingService running as PID $PID"
else
        echo "fingService is not running"
        perl /opt/fhem/fhem.pl $fhemHost:$fhemHostTelnetPort "setreading $fhemDefine info fingService is not running"
fi
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
exit 1
;;
esac

 
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: stromer-12 am 03 Juni 2017, 18:18:46
Versuche mal pidof mit "-x" zu benutzen.
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: betateilchen am 03 Juni 2017, 18:21:42
oder mit -s ;)

Ein bash skript kann seine eigene pid übrigens einfach über $$ ermitteln.

Gib mal auf der Konsole "echo $$" ein und staune.

Wie man ein perl Skript per init.d startet, kannst Du Dir doch am mitgeliefereten init-Skript von FHEM anschauen, da wird genau das gemacht.
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 18:52:06
Wow, super schnell. Danke betateilchen und Stromer-12.
fhem@FHEMDEV:~$ pgrep -f fingService
2292
fhem@FHEMDEV:~$ pidof -s fingServie
fhem@FHEMDEV:~$ pidof -x fingServie
fhem@FHEMDEV:~$ echo $$
2985
fhem@FHEMDEV:~$


diese Parameter habe ich sicherheitshalber auf eure Empfehlung hin nocheinmal versucht. Leider ohne Erfolg (s.o.). Der echo $$ Befehl funktioniert, aber wie kann ich den im init.d Skript verwenden?
Wenn ich das richtig verstehe, müsste er im eigentlichen Perl Skript verwendet werden und über eine Datei an das init.d weitergeben werden, oder. gibt es eine elegantere Lösung.

Warum gibt pidof keinen Wert aus, das verstehe ich nicht?

Danke,

Gernot
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: stromer-12 am 03 Juni 2017, 18:54:54
Zitat von: supernova1963 am 03 Juni 2017, 18:52:06
Wow, super schnell. Danke betateilchen und Stromer-12.
fhem@FHEMDEV:~$ pgrep -f fingService
2292
fhem@FHEMDEV:~$ pidof -s fingServie
fhem@FHEMDEV:~$ pidof -x fingServie
fhem@FHEMDEV:~$


Warum gibt pidof keinen Wert aus, das verstehe ich nicht?

Dein gesuchtes Programm heißt ja auch anders.
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 19:03:13
An-für-sich heißt das gestartete Programm /opt/fhem/www/fing/fingService.pl, und es wird von pgrep ja auch gefunden.?
Oder hast du einen Fehler entdeckt?

Danke,

Gernot
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 19:09:01
Sorry, du hast recht das Programm heißt Perl.

Wenn ich das eingebe kommt die PID, aber leider auch noch einige andere

fhem@FHEMDEV:~$ pidof perl
2292 1298 1287
fhem@FHEMDEV:~$
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: stromer-12 am 03 Juni 2017, 19:16:39
Du hast bei den pidof das c im Programmnamen vergessen.
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 19:20:42
Danke, ich hab's korrigiert, aber das Ergebnis bleibt gleich:

fhem@FHEMDEV:~$ pidof -s fingService
fhem@FHEMDEV:~$ pidof -x fingService
fhem@FHEMDEV:~$
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: SabineT am 03 Juni 2017, 19:32:22
Zitat von: supernova1963 am 03 Juni 2017, 19:09:01
Wenn ich das eingebe kommt die PID, aber leider auch noch einige andere

fhem@FHEMDEV:~$ pidof perl
2292 1298 1287
fhem@FHEMDEV:~$

probier mal
ps xf | grep 'perl fhem.pl' | grep -v '\_' | cut -d ' ' -f 1
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: betateilchen am 03 Juni 2017, 20:28:41
ich kapiere immer noch nicht, was Du eigentlich als Ergebnis haben willst und wozu Du das brauchst.
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 20:38:12
Hallo SabineT,

Danke für deinen Tip. Ich hab's versucht:

fhem@FHEMDEV:~$ ps xf | grep 'perl fhem.pl' | grep -v '\_' | cut -d ' ' -f 1

fhem@FHEMDEV:~$ ps xf
  PID TTY      STAT   TIME COMMAND
4779 ?        S      0:00 sshd: fhem@pts/3
4780 pts/3    Ss     0:00  \_ -bash
4792 pts/3    R+     0:00      \_ ps xf
2285 ?        S      0:00 sshd: fhem@pts/2
2286 pts/2    Ss+    0:00  \_ -bash
2292 pts/2    S      0:00      \_ /usr/bin/perl -w /opt/fhem/www/fing/fingServic 1494 ?        S      0:00 sshd: fhem@pts/1
1495 pts/1    Ss+    0:00  \_ -bash
1410 ?        S      0:00 sshd: fhem@pts/0
1411 pts/0    Ss+    0:00  \_ -bash
1334 ?        Ss     0:00 /lib/systemd/systemd --user
1335 ?        S      0:00  \_ (sd-pam)
1287 ?        S      0:04 perl fhem.pl fhem.cfg
fhem@FHEMDEV:~$ ps xf | grep 'perl fhem.pl'
4795 pts/3    S+     0:00      \_ grep perl fhem.pl
1287 ?        S      0:04 perl fhem.pl fhem.cfg
fhem@FHEMDEV:~$ ps xf | grep 'perl fhem.pl' | grep -v '\_'
1287 ?        S      0:04 perl fhem.pl fhem.cfg
fhem@FHEMDEV:~$ ps xf | grep 'perl fhem.pl' | grep -v '\_' | cut -d ' ' -f 1

fhem@FHEMDEV:~$


Wenn ich deine grep Funktionen richtig verstehe geht das in Richtung PID von fhem. Ich benötige jedoch die PID 2292 .... fingService.

Wenn's keine einfachere Möglichkeit gibt, versuche ich deinen Vorschlag zu verstehen und umzuschreiben.

Alternativ wäre auch ein Start in myUtils. Da schreckt mich aber derzeit noch die blocking bzw. subprocess Thematik ab.

Gernot

@betateilchen:  mit dem Perl Skript lese die stout Ausgaben von dem Programm overlook fing aus und lege dummies in Fhem an

Hier der Code:

fhem@FHEMDEV:~$ cat /opt/fhem/www/fing/fingService.pl
#!/usr/bin/perl -w
package main;
use strict;
use warnings;
use POSIX;
use LWP::Simple;
use v5.18.2;
use Net::Telnet ();
#use Blocking;
#use XML::LibXML;

my ($fingbefehl) = @ARGV;
my @array;
my $devicename='';
my $nr = 0;
my $FHEMBefehl = '';
my $regex = qr/:/p;
my $subst = '_';
my $telnet = new Net::Telnet ( Timeout=>10, Errmode=>'die');
$telnet->open(Port=>'7072');
#$telnet->waitfor('/Password:/');
#$telnet->print('97895');

$FHEMBefehl = 'set group=NetClients down';
$telnet->print($FHEMBefehl);
open FINGDUMP, "-|", "sudo fing -n 192.168.1.105/24 -o log,csv,console";
while (<FINGDUMP>) {
   
    my ($Uhrzeit,$Action) = split(/>/);
    my ($Zeitpunkt,$Status,$IP,$Name,$Hostname,$MAC,$Vendor) = split(/;/);
    if (defined($Action)) {
        my ($Netzkennung,$Netz)=split(/Discovery on:/,$Action);
        my ($Fortschrittkennung,$Fortschritt)=split(/Discovery progress /,$Action);
        if (defined($Netz)) {
            $Netz =~ s/      //;
        }
        elsif (defined($Fortschritt)) {
            $Fortschritt =~ s/\%//;
        }
        else {
        }
    }
    elsif (defined($MAC)) {
        $nr = substr($IP,rindex($IP,'.')+1);
        $nr = substr("000".$nr, -3, 3);
        $devicename = $MAC;
        $devicename ='nc_'.$devicename =~ s/:/_/rg;
        $FHEMBefehl = 'defmod '.$devicename.' dummy';
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'setreading '.$devicename.' IP '.$IP;
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'setreading '.$devicename.' MAC '.$MAC;
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'setreading '.$devicename.' state '.$Status;
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'setreading '.$devicename.' NR '.$nr;
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'attr '.$devicename.' sortby '.$nr;
        $telnet->print($FHEMBefehl);
        if (length($Name)>2) {
            $FHEMBefehl = 'attr '.$devicename.' alias '.$Name;
            $telnet->print($FHEMBefehl);
        }
        if (length($Hostname)>2) {
            $FHEMBefehl = 'setreading '.$devicename.' HOSTNAME '.$Hostname;}
        else {
            $FHEMBefehl = 'setreading '.$devicename.' HOSTNAME n/a';
        }
        $telnet->print($FHEMBefehl);
        if (length($Vendor)>2) {
            $FHEMBefehl = 'setreading '.$devicename.' VENDOR '.$Vendor;}
        else {
            $FHEMBefehl = 'setreading '.$devicename.' VENDOR n/a'}
        $telnet->print($FHEMBefehl);
        #Attribut group setzen, damit die NetClient Dummy's in einem Raum zusammengefaßt angelistet werrden
        $FHEMBefehl = 'attr '.$devicename.' group NetClients';
        $telnet->print($FHEMBefehl);
        # Attribut room setzen, damit die NetClient Dummy's einem Raum zugeordnet werden
        $FHEMBefehl = 'attr '.$devicename.' room Netz';
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'setreading nc_init nc '.$devicename;
        $telnet->print($FHEMBefehl);
        $FHEMBefehl = 'setreading nc_init ncAnlageStandard on';
        $telnet->print($FHEMBefehl);
        $telnet->print('save');
    }
    else {
        printf "";
    }
}
close FINGDUMP;
$telnet->print('exit');
fhem@FHEMDEV:~$


Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: SabineT am 03 Juni 2017, 20:58:50
Dann müsste so gehen:
ps xf | grep 'fingServic' | cut -d ' ' -f 1

fingServic darf halt dann nur 1x laufen. Ansonsten müsstest du das grep entsprechend erweitern. Also im Extremfall
ps xf | grep '\_ /usr/bin/perl -w /opt/fhem/www/fing/fingServic' | cut -d ' ' -f 1

Im Prinzip rufe ich erst mal ps xf auf, der output wird dann aber mit dem | an das grep als input übergeben. Das grep filtert dann einfach genau die Zeile raus, die dein gewünschtes Programm enthält. Und das cut schneidet dann das erste Feld der Zeile heraus, also die PID.
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 21:18:19
Super, das ist fast perfekt. Diese PID Suche soll u.A. verhindern, dass es doppelt ausgeführt wird.
Hast du noch eine Idee, wie man so genial ausschließen kann, dass die PID von grep mit dem Suchbegriff angezeigt wird?
Hinweis: der cut muss bei dem 2. Leerzeichen erfolgen:
fhem@FHEMDEV:~$ ps xf | grep 'fingServic' | cut -d ' ' -f 2
5842
2292

Vielen, vielen Dank,

Gernot
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: SabineT am 03 Juni 2017, 21:25:59
Dann mach
ps xf | grep 'fingServic' | grep -v grep | cut -d ' ' -f 2

Das 'grep -v grep' lässt alles durch, was nicht grep in der Zeile stehen hat
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 21:29:52
Einfach genial, so funktioniert's

fhem@FHEMDEV:~$ ps xf | grep 'fingServic' | grep -v grep | cut -d ' ' -f 2
2292
fhem@FHEMDEV:~$


Danke, ich selten in so kurzer Zeit soviel gelernt,

Gernot
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: stromer-12 am 03 Juni 2017, 21:40:41
Die Zeile sollte kürzer auch so gehen:

ps fx | grep [f]ingServic | cut -c-5

bei 5stelliger PID ist es mit der anderen Version wieder -f1
Titel: Antw:In init.d - PID ermitteln um Perl-Skript zu starten/stoppen/restarten/Status
Beitrag von: supernova1963 am 03 Juni 2017, 21:55:16
Danke für den Hinweis, Stromer-12.

Ich probiere es gleich morgen aus,

Gernot