Autostart eines Dienstes blockiert den RasPi

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,[/code]
    mit Hilfe des Forums habe ich mir ein Skript gebastelt, das händisch gestartet gut funktioniert.

    Code
    sudo screen -S rollo /home/pi/skripte/fhem/./rollo-web.sh start


    Nun möchte ich dies automatisieren. Darum habe ich es entsprechend dem Autostart-Tutorial ergänzt, in den Ordner /etc/init.d/ gelegt sowie einen Sym-Link vom Ordner /etc/rc2.d/ darauf erzeugt. Das Skript gehört [root] mit den Rechten 777.
    Danach folgenden Befehl ausgeführt:

    Code
    cd /etc/init.d
    sudo update-rc.d rollo-web1.sh defaults
    update-rc.d: using dependency based boot sequencing
    insserv: warning: current start runlevel(s) (2) of script `rollo-web1.sh' overrides LSB defaults (2 3 4 5).
    insserv: warning: current stop runlevel(s) (empty) of script `rollo-web1.sh' overrides LSB defaults (0 1 6).


    Trotz dieser Warnung machte ich einen Neustart und kann ich mich nicht mehr via Putty verbinden. Ich habe das Backup-Image eingespielt.
    Das Skript sieht verkürzt so aus:


    Habe ich bei meinem Skript oder bei der Einbindung was falsch verstanden?

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Wieso willst du das über Runlevel (init.d) ausführen lassen?
    Bitte beachte Beitrag#11 aus dem Anleitungsthread - meiner Meinung nach íst der erste Beitrag nicht so gut..

    Davon abgesehen wird dein init.d Script nicht in einem Screen ausgeführt und somit ist freilich klar das es den Bootvorgang dann blockiert/behindert. Wie gesagt -> Beachte Beitrag#11 und nutze die ersten Möglichkeiten, nicht aber init.d, das is eher für Erfahrene Anwender aber auch nur ganz selten nötig.

  • Eine Lösung mit crontab würde ich auch sehr bevorzugen, zumal ich das einigermaßen verstanden habe.
    Jedoch klappt das Script leider nicht mit crontab.

    Code
    @reboot /home/pi/skripte/fhem/rollo-web.sh >> /home/pi/skripte/fhem/z-kontrolle$

    Und es hatte wohl auch der Ideengeber meines Skripts (siehe HIER die letzten Zeilen) eine Lösung mit init.d vor. Leider meldet er sich nicht mehr und ich möchte nicht nerven.

    Mein hier vorgestelltes Skript ist ja auch stark gekürzt auf das Wesentliche, worauf es bei diesem Problem (Autostart) ankommt. (hoffe ich zumindest).

    Wie gesagt, das Skript macht seit Monaten seine Arbeit gut, wenn ich es mit

    Code
    sudo screen -S rollo /home/pi/skripte/fhem/./rollo-web.sh start


    händisch starte und dann mit <Strg+a> und <Strg+d> in den Hintergrund schicke.
    Also der Screen-Befehl hat nichts mit init.d zu tun, wollte nur sagen, dass das Skript ansonsten funktioniert.

    Ich muss wohl eine Lösung mit Runlevel und init.d finden, auch wenn ich da sehr schwimme...

    EDIT:
    Den LSB Header hatte ich aus dem Tutorial übernommen, weil ich dachte, dass er zu meinem Skript passen könnte.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

    Einmal editiert, zuletzt von docadams (20. April 2015 um 16:32)

  • Wie gesagt - du startest es manuell anders als über Autostart und genau hier liegt dein Problem.

    Du musst also entweder das Script via Autostart auf die gleiche Weise ausführen - oder du musst dir eine andere Möglichkeit suchen :fies:
    Der Punkt in mitten des absoluten Pfades ist übrigens überflüssig.

    Also zunächst mal kannst du über den screen Befehl etwas direkt in den Hintergrund schicken, ohne noch mal manuell STRG+A usw drücken zu müssen:

    Code
    screen -dmS rollo /home/pi/skripte/fhem/rollo-web.sh start

    Damit würde eine neue Session namens 'rollo' in den Hintergrund geschickt werden. In die kannst du dann jederzeit rein gucken (attach'en) indem du folgendes ausführst und dann zB einfach dein SSH Client wieder schließt wenn du fertig bist, die Session läuft dann trotzdem weiter:

    Code
    screen -r rollo

    An diese Session kannst du auch Befehle schicken:

    Code
    screen -S rollo -X stuff $'ls -l\n'

    stuff muss unverändert bleiben wie auch das $ Zeichen, nur das innerhalb ' ist veränderbar. Das wird dann direkt rein in die Session gesendet - kannst du am besten mal testen indem du dich in die Session attachest und über ein 2.Terminal den Befehl absetzt.

    So kannste die Session dann nämlich auch beenden:

    Code
    screen -S rollo -X quit

    -X führt halt einen Befehl aus...

    Mehr dazu wie immer in der manual Page: man screen


    Wenn du also ein Script zum starten und beenden dieses Screens nutzen willst, verwende oben erwähnte Befehle. Bevor du aber einfach "start" ausführst solltest du mithilfe 'screen -ls' prüfen ob nicht bereits eine Session mit dem Name läuft... Sonst kann es passieren das es mehrmals ausgeführt wird, was nicht so toll wäre.


    Es gibt btw auch noch weitere Möglichkeiten etwas im Hintergrund auszuführen

    Code
    nohup
    at
    watch


    Quelle: http://www.thegeekstuff.com/2010/12/5-ways…-linux-command/

  • Ich habe gestern bei draußen herrlichstem Sonnenschein drinnen 2 Stunden im Nebel gestochert. Aber ich begreife es nicht.
    Wie gesagt, händisch lässt sich das Skript so starten und in den Hintergrund bringen.

    Code
    sudo screen -S rollo /home/pi/skripte/fhem/./rollo-web.sh start


    Es wird eine Datei /home/pi/rollo.pid erzeugt, die ausgewertet wird. Soweit läuft es.

    Mit

    Code
    pi@fhem2 ~ $ screen -dmS rollo /home/pi/skripte/fhem/rollo-web.sh start
    pi@fhem2 ~ $ screen -ls
    There is a screen on:
            3523.rollo      (2015-04-22 14:44:13)   (Detached)
    1 Socket in /var/run/screen/S-pi.


    läuft es auch soweit, das Skript gestartet wird.
    Es wird die DO-Schleife gestartet:

    Code
    PID=$$
      echo "PID: ${PID}"
      echo "${PID}" > rollo.pid
      cd /var/www/
      while :;
      do
    .......
          sleep 1
      done


    aber die dazwischen liegenden Funktionen nicht. Wird das hier irgendwie anders gehandelt?
    Müsste da nicht eher die Datei /var/run/screen/S-pi/*.rollo ausgewertet werden?

    Und letztendlich, wie bringe ich das in den Autostart?
    In crontab -e ein

    Code
    $reboot screen -dmS rollo /home/pi/skripte/fhem/rollo-web.sh start


    bringt eine Warnmeldung

    Code
    crontab: installing new crontab
    "/tmp/crontab.zarGSh/crontab":70: bad command
    errors in crontab file, can't install.
    Do you want to retry the same edit? (y/n)

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,


  • $reboot gibt es für crontab nicht, nur @reboot


    Wenn ich schon mal was selber kreiere...
    Bleibt aber mein Hauptproblem.
    Ich hänge das ganze Skript mal an, wie es händisch gestartet gut arbeitet. Ich hoffe, dass es nicht zu wirr ist.
    Die Grundidee stammt von ruedigerp, ich habe das nur um meine Gegebenheiten angepasst und ergänzt. Etliche Funktionen (Rollos ansteuern, Abfrage usw.) habe ich in Extraskripte (Module) ausgelagert, weil ich sie noch in anderen Programmen (z.B. regelgesteuertes Bedienen der Rollos) ebenfalls brauche und um für mich die Übersicht zu bewahren.

  • Du solltest dringenst mit absoluten Pfaden arbeiten, also bei zB. "rollo.pid" nicht annehmen das diese Datei auch wirklich im aktuellen Verzeichnis erstellt wird, sondern den absoluten Pfad zu dieser Datei angeben. Das selbe gilt für die *.asc Dateien. Hierzu wäre es auch besser wenn die in einem tmpfs Ordner abgelegt werden um die SD nicht unnötig mit Schreibvorgängen zu belasten.
    Das könnte schon der Grund sein wieso es nicht über crontab funktioniert, da dort nicht erst ins Verzeichnis /home/pi/ gewechselt wird..

    Bearbeite mal die Datei /etc/default/tmpfs und setze dort RAMTMP=yes
    Anschließend rebooten.

    Nun weiß ich nicht genau was /home/pi/skripte/quelle beinhaltet oder welche anderen Dateien du sonst noch nutzt - aber pass das rollo-web.sh mal wie folgt an:

    &quot;rollo-web.sh&quot;


    [code=php]
    #!/bin/bash
    #
    . /home/pi/skripte/quelle
    zahl=0
    PIDFILE=/tmp/rollo.pid
    ASCPATH=/var/www
    ##################################################################
    #
    function STOPP()
    {
    # echo 0 > /sys/class/gpio/$rel8/value
    # echo 0 > /sys/class/gpio/$rel7/value
    echo 0 > /sys/class/gpio/$rel6/value
    echo 0 > /sys/class/gpio/$rel5/value
    echo 0 > /sys/class/gpio/$rel4/value
    echo 0 > /sys/class/gpio/$rel3/value
    echo 0 > /sys/class/gpio/$rel2/value
    echo 0 > /sys/class/gpio/$rel1/value
    }
    #
    ##################################################################

    function toeten()
    {
    if [ -e $PIDFILE ]; then
    PID=$(cat $PIDFILE)
    echo "Beende $(basename $0) mit PID: $PID"
    kill $PID
    rm $PIDFILE
    exit 0;
    else
    echo "Kann PID nicht lesen."
    exit 1;
    fi
    }

    ###########################################################################
    ###########################################################################

    function run()
    {
    PID=$$
    echo "PID: $PID"
    echo $PID > $PIDFILE
    while :; do
    #
    ########## N O T S T O P P ##########################
    #
    if [ -e $ASCPATH/stopp.asc ]; then
    echo "Alles STOPP !!!"
    rm $ASCPATH/stopp.asc
    ## sudo /home/pi/skripte/fhem/stopp.sh
    STOPP
    fi
    #
    ################# Fenster 1 ########################
    #
    if [ -e $ASCPATH/f1h.asc ]; then
    #echo "Fenster 1 hoch."
    rm $ASCPATH/f1h.asc
    #F1H& # die Funktion!! siehe oben ursprünglich:
    sudo /home/pi/skripte/fhem/f1h.sh &
    fi
    #
    if [ -e $ASCPATH/f1rk.asc ]; then
    #echo "Fenster 1 halbrunter."
    rm $ASCPATH/f1rk.asc
    sudo /home/pi/skripte/fhem/f1rk.sh &
    fi
    #
    if [ -e $ASCPATH/f1r.asc ]; then
    #echo "Fenster 1 runter."
    rm $ASCPATH/f1r.asc
    sudo /home/pi/skripte/fhem/f1r.sh &
    fi
    #
    ################# Fenster 2 ########################
    #
    if [ -e $ASCPATH/f2h.asc ]; then
    #echo "Fenster 2 hoch."
    rm $ASCPATH/f2h.asc
    sudo /home/pi/skripte/fhem/f2h.sh &
    fi
    #
    if [ -e $ASCPATH/f2rk.asc ]; then
    #echo "Fenster 2 halbrunter."
    rm $ASCPATH/f2rk.asc
    sudo /home/pi/skripte/fhem/f2rk.sh &
    fi
    #
    if [ -e $ASCPATH/f2r.asc ]; then
    #echo "Fenster 2 runter."
    rm $ASCPATH/f2r.asc
    sudo /home/pi/skripte/fhem/f2r.sh &
    fi
    #
    ################# Fenster 3 ########################
    #
    if [ -e $ASCPATH/f3h.asc ]; then
    #echo "Fenster 3 hoch."
    rm $ASCPATH/f3h.asc
    sudo /home/pi/skripte/fhem/f3h.sh &
    fi
    #
    if [ -e $ASCPATH/f3rk.asc ]; then
    #echo "Fenster 3 halbrunter."
    rm $ASCPATH/f3rk.asc
    sudo /home/pi/skripte/fhem/f3rk.sh &
    fi
    #
    if [ -e $ASCPATH/f3r.asc ]; then
    #echo "Fenster 3 runter."
    rm $ASCPATH/f3r.asc
    sudo /home/pi/skripte/fhem/f3r.sh &
    fi
    #
    ################## Lichtsteuerung ########################
    #
    if [ -e $ASCPATH/l-an.asc ]; then
    #echo "Fenster-LED an"
    rm $ASCPATH/l-an.asc
    sudo /home/pi/skripte/fhem/l-an.sh
    fi
    #
    if [ -e $ASCPATH/l-aus.asc ]; then
    #echo "Fenster-LED aus"
    rm $ASCPATH/l-aus.asc
    sudo /home/pi/skripte/fhem/l-aus.sh
    fi
    #
    ################# Automatic wieder aktivieren ########################
    #
    if [ -e $ASCPATH/aut-aus.asc ]; then
    zahl=$(( $zahl + 1 ))
    if [ $zahl = 1 ]; then
    echo $(date +%d.%m_%H:%M) Automatic manuell deaktiviert >> /home/pi/skripte/fhem/z-kontrolle.log
    fi
    #echo $zahl
    if [ $zahl = 5 ];then
    zahl=2
    fi
    #
    timeNow=$(date +%H%M)
    if [[ "$timeNow" = 2359 ]]; then # Mitternacht wird Automatic auf jeden Fall akticiert
    rm $ASCPATH/aut-aus.asc
    echo $(date +%d.%m_%H:%M) Automatic automatisch aktiviert >> /home/pi/skripte/fhem/z-kontrolle.log
    fi
    fi
    #
    if [ -e $ASCPATH/aut-an.asc ]; then
    rm $ASCPATH/aut-aus.asc
    rm $ASCPATH/aut-an.asc
    zahl=0
    echo $(date +%d.%m_%H:%M) Automatic manuell aktiviert >> /home/pi/skripte/fhem/z-kontrolle.log
    fi

    ## Fernabfrage, wo Rollos stehen
    if [ -e $ASCPATH/abfrage.asc ]; then
    rm $ASCPATH/abfrage.asc
    /home/pi/skripte/fhem/abfrage.sh &
    fi
    #
    #
    ################################################################################
    # ACHTUNG: dieser Teil erstellt das WebLog, das in rollo.html dargestellt wird,
    # hat also nichts direkt mit dem hier zu tun
    cat /home/pi/skripte/fhem/z-rollo.log | tail -n20 > /home/pi/skripte/fhem/z-rollo-k.log
    cat /home/pi/skripte/fhem/z-kontrolle.log | tail -n20 > /home/pi/skripte/fhem/z-kontrolle-k.log
    tac /home/pi/skripte/fhem/z-kontrolle-k.log /home/pi/skripte/temperatur/zwischen.log /home/pi/skripte/fhem/z-rollo-k.log > /home/pi/skripte/fhem/z-weblog.log
    #################################################################################

    sleep 1
    done
    }

    ###########################################################################
    ###########################################################################

    function status()
    {
    echo -n "PID-File: $PIDFILE "
    if [ -e $PIDFILE ]; then
    echo "vorhanden. $(cat $PIDFILE)"
    ps fauxww | grep $(cat $PIDFILE) | grep -v grep
    else
    echo "nicht vorhanden. "
    fi
    }

    ###############################################################

    case "$1" in
    start)
    run
    ;;
    stop)
    toeten
    ;;
    status)
    status
    ;;
    *)
    echo "Usage: $0 {start|stop|status}"
    ;;
    esac

    exit 0
    [/php]

    Zunächst hab ich PIDFILE festgelegt wodurch man nur oben diese Variable verändern müsste und den restlichen Code so lassen kann. Das ist nun ein absoluter Pfad und somit spielt es keine Rolle ob man sich aktuell im richtigen Verzeichnis befindet..
    Dann hab ich den Pfad für die *.asc Dateien ebenfalls oben eingestellt und jeweils im Code angepasst - ist nun also auch ein absoluter Pfad.

    Und dann hab noch diese komischen " $(sudo /home/pi/skripte/fhem/f1h.sh)& " usw geändert da das so kein Sinn ergibt - zum einen weil das eine mögliche Rückgabe des Befehls ausgeben würde, also wie bei einer Variable oder dem cat PIDFILE ... zum anderen wird es aber in den Hintergrund geschickt also kann auch keine Rückgabe erfolgen :fies:
    Allerdings führst du da fast jedes Script noch mal extra über sudo aus - was eigentlich auch überflüssig ist sofern das rollo-web.sh bereits als root oder mit sudo ausgeführt wird, denn dann wird alles dadrin ebenfalls mit root Rechten ausgeführt.

    Und zu guter letzt sind Punkte innerhalb absoluter Pfade überflüssig. /home/pi/skripte/fhem/./stopp.sh wäre also Quatsch, es reicht /home/pi/skripte/fhem/stopp.sh

    Ich empfehle dir außerdem die functions in eine gesonderte Datei auszulagern und dann wie 'quelle' nur noch zu includen. Das machts einfacher sofern du vor hast diese Funktionen auch noch in anderen Scripts zu verwenden, dann musst du nicht 10x die eigentlich selbe Function ändern. Auch könntest du diese "f1.sh" usw in einem Script zusammenfassen und nur ein Parameter übergeben wie eben "f1".. Somit hättest du dann nicht 10 verschiedene kleine f*.sh Scripts ;)

    Die *.asc würde ich wie gesagt ebenfalls in /tmp/ ablegen wegen der unnötigen/ständigen Schreibzugriffe.

  • Was nimmst du eigentlich für die Privatstunde, bevor es zu teuer wird ;)

    Vielen Dank für die Rückmeldung. Ich muss das erst mal verdauen und melde mich, wenn ich es umgesetzt habe.

    Eine Antwort kann ich schon geben. In der /home/pi/skripte/quelle liegen Konstanten, die ich immer mal ändern/anpassen muss, also z.B. Grenztemperaturen, ab wann das Rollo wg. zu heißer Sonneneinstrahlung runter fährt, Dauer des Runterfahrens, Zeitpunkt, wann pro Woche die Rollos hoch und runter sollen usw.

    Wenn ich in so eine zentrale Datei auch die Funktionen, die ich derzeit noch in den von dir monierten Einzeldateien habe, auch so zusammen fassen kann, ist mir das sehr recht. Das würde die Anzahl der Skripte im Ordner ../skripte/fhem sehr reduzieren.

    Also vielen Dank noch mal für die Tipps.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

  • Zu meinem Hauptproblem (Skript lässt sich nicht automatisch in den Hintergrund starten): Ich habe den Irrtum gefunden und ärgere mich jetzt, dass ich nicht alleine drauf gekommen bin.
    Das Skript konnte ja schon immer händisch mit

    Code
    sudo screen -S rollo /home/pi/skripte/fhem/./rollo-web.sh start

    gestartet werden. Also muss es auch mit crontab mit Rootrechten gestartet werden:

    Code
    @reboot [b]sudo [/b]screen -dmS rollo /home/pi/skripte/fhem/rollo-web2.sh start


    Um meinen alten Chef aus uraltet Zeitet zu zitieren: So einfach ist das!

    meigrafd
    Deine Hinweise habe ich umgesetzt, war deutlich einfacher, als es für mich zunächst aussah. Jetzt ist der Ordner wieder wesentlich übersichtlicher. Vielen Dank. :bravo2:

    Jetzt liegen in meinem Webordner (/var/www/) noch jede Menge PHP-Dateien, die die entsprechenden *.asc-Dateien erzeugen.

    Code
    <?PHP
     $handle = fopen("/tmp/f1h.asc", "w");
     header ("location:rollo.html");
     close($handle);
     ?>


    Für jede meiner 20 Steuerbefehle. Könnte man das auch so zusammenfassen?
    Oder geht das eher in Richtung Webprogrammierung?

    Ich möchte aber jetzt hier kein neues Thema anhängen, das Problem ist erledigt. Nur mal so zur Info, meine Steuerseite sieht im Handy so aus.


  • Jetzt liegen in meinem Webordner (/var/www/) noch jede Menge PHP-Dateien, die die entsprechenden *.asc-Dateien erzeugen.

    Code
    <?PHP
     $handle = fopen("/tmp/f1h.asc", "w");
     header ("location:rollo.html");
     close($handle);
     ?>


    Für jede meiner 20 Steuerbefehle. Könnte man das auch so zusammenfassen?

    Ja das ist ähnlich wie in bash/python - wobei es darauf ankommt wie dein PHP Code allgemein aussieht ...
    Die einzelnen Sachen zum schreiben der asc's könntest du auch in functions setzen.
    Zum Beispiel:

    [code=php]
    function create_asc($file, $value) {
    $handle = @fopen($file, 'a');
    @fwrite($handle, $value);
    @fclose($handle);
    }
    [/php]Aufruf:
    [code=php]create_asc("/tmp/f1h.asc", "1");[/php]

    Die @ bewirken dass Fehlermeldungen wie zB "Kann Datei nicht öffnen" o.ä., also Ausgaben der fopen ; fwrite oder fclose Befehle, ignoriert werden.

    Oder du legst nur eine PHP Datei an an die du via $_GET die entsprechenden Sachen übergibst, so brauchst du dann an deinen Buttons nicht viel ändern.
    Zum Beispiel:

    [code=php]
    <?php
    if (isset($_GET['file']) && isset($_GET['value'])) {
    $handle = @fopen("/tmp/".$_GET['file'], 'a');
    @fwrite($handle, $_GET['value']);
    @fclose($handle);
    }
    ?>
    [/php]Aufruf:[code=php]<a href="create_asc.php?file=f1h.asc&value=1">erstelle f1h</a>[/php]..oder ähnlich..

  • Bevor ich hier ganz zu mache noch eine kleine Rückmeldung.
    Der zweite Weg, also wo das eine Skripte die jeweilige *asc-Datei erzeugt, gefällt mir und das habe ich umgesetzt.
    Das klappt wunderbar und das werde ich wahrscheinlich noch an anderer Stelle machen. :bravo2:
    Also vielen Dank noch mal.

    Viele Grüße
    DocAdams

    1x RaspberryPi 2, 1x RaspberryPi 3, 1x OpenELEC, 1x RaspberryPi 4 mit ioBroker ,

    Einmal editiert, zuletzt von docadams (6. Mai 2015 um 11:54)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!