Script starten mit /etc/rc.local

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo Experten,

    habe eine Lichtsteuerung mit folgendem Script auf einem einem RPiZero gebaut:

    https://github.com/luemar/lights_…b/main/licht.py

    Ich möchte die Steuerung mit einer Funksteckdose ein - und ausschalten

    und habe dazu das Script in < /etc/rc.local> eingetragen.

    Nach hinunterfahren des RPi über <shutdown now>, ab- und wieder

    einschalten der Stromversorgung bzw. der Funksteckdose ist das Script

    aber nicht gestartet. Geht das nur über eine service unit in systemd ?

    Wozu denn überhaupt rc.local ??

  • luemar Weitere Anmerkungen zum Quelltext: `system` wird aus `os` importiert, aber nirgends verwendet. Sollte es auch nicht wirklich. Die Dokumentation von der Funktion weist auf das `subprocess`-Modul hin, zum ausführen von externen Programmen.

    `spot_gallerie` wird definiert, aber nirgends verwendet.

    Der erste Wert der `t` zugewiesen wird, wird nirgends verwendet, die Zuweisung an der Stelle kann man sich also sparen.

    Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

    Wenn die Adresse vom Lichtsensor als Konstante definiert ist, dann sollte die nicht noch mal irgendwo später in einem Kommentar stehen. Denn wenn die sich mal ändert, ändert man die Konstante und geht ziemlich sicher nicht nochmal den ganzen Quelltext durch ob die noch mal irgendwo steht und angepasst werden muss. Damit man das nicht machen muss, definiert man das ja gerade als Konstante.

    Im Code hast Du dann auch zwei Aufrufe von `write_byte_data()` direkt hintereinander stehen, wo der erste die Konstante verwendet und der zweite nicht‽

    Beim auslesen von Helligkeit und Infrarothelligkeit steht fast der gleiche Code. Diese Codewiederholung sollte man in eine Funktion heraus ziehen.

    Sich mit `time.ctime()` eine Zeichenkette zu erzeugen aus der man dann Stunden und Minuten raus parst ist unnötig umständlich und schwer zu lesen. Für so etwas gibt es das `datetime`-Modul.

    `t_start_min` ist ein irreführender Name. Wofür steht das `min`? Für Minuten oder für minimal? Der Wert ist in Sekunden, aber er wird ausgegeben mit den Text "aktuelle Zeit bei Start licht.py in Minuten", obwohl es ja keine Minuten sind. Und später wird der Wert dann auch mit Sekunden verrechnet. Also ist wohl der ausgegebene Text falsch, und man sollte das `min` besser aus dem Namen entfernen.

    Es ist immer besser wenn man Code so schreibt, dass man den nicht mit Kommentaren erklären muss. Diese magischen Sekundenzahlen sind nicht leicht verständlich, die sollte man zur Laufzeit ausrechnen, und zwar so, dass man am Code schon erkennen kann, was die in menschlich verständlicher Form bedeuten.

    Zwischenstand (ungetestet):

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • vielen Dank für die hilfreichen Kommentare.

    1. Zum Autostart: Verstehe ich das richtig, wenn die Methode mit

    /etc/rc.local "veraltet" ist, heisst das, dass so kein Autostart mehr zustande kommen kann und dass das nur noch über eine service unit geht ?

    2. Zum Script: Mein Code funktioniert zwar - nur (noch) nicht der

    Autostart - werde ihn aber gerne zu einer korrekten "pythonischen"

    Version korrigieren und auf github ersetzen.

    Den ersten Teil, das Auslesen des Lichtsensors, habe ich direkt als library

    von der Adafruit website für TSL2561 heruntergeladen bzw. kopiert.

    • Offizieller Beitrag

    Zwei Fragen hätte ich noch.

    1.

    Ich möchte die Steuerung mit einer Funksteckdose ein - und ausschalten

    Das mit der Funksteckdose verstehe ich nicht. was willst Di ein und ausschalten?

    2. Woran siehst Du, dass das Skript (von den angesprochenen Fehlern mal abgesehen) nach einem Neustart nicht funktioniert?


    //Edit: Eine dritte Frage: Was ist nach einem Neustart die Ausgabe von ps ax | grep licht.py?

  • also eines nach dem anderen:

    nach anlegen der datei neue_datei.py passiert mit dem Befehl <touch> nichts bzw. wie wenn man die Eingabetaste drückt.

    Mit der Funksteckdose möchte ich ich über die dazugehörige Fersteuerung, also mit einem Tastendruck

    den RPi und damit mein Script bzw.die Lichtsteuerung starten ohne dass ich jedesmal das Script über PuTTy und das Eingabefenster starten muss.

    Die Ausgabe nach Neustart und ps ax | grep licht.py

    ergibt: 789 pts/0 S+ 0:00 grep licht.py

  • Hallo,

    was passiert wenn du das Skript manuell startest? Läuft und funktioniert es? Wenn nicht was geht nicht? Gibt es Fehlermeldungen? Wenn ja welche?

    Bitte erkläre alles immer so ausführlich wie möglich.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

    • Offizieller Beitrag

    Läuft es nach dem Neustart oder funktioniert es nur nicht? Solange der Autostart nicht funktioniert, bleibt es bei Spekulatius.

    Schreib doch mal ein Skript, das immer funktionieren sollte, also keine Abhängigkeiten braucht. Vielleicht sowas hier:

    Dann mach das ausführbar und versuch das automatisch starten zu lassen. Danach lass Dir mir ps ax | grep test.py die PID anzeigen. Siehst Du nur eine Zeile, die grep enthält, dann läuft es nicht.

    Btw. Wie hast Du Dein Skript genau starten lassen wollen?

  • Ich habe das Script von __blackjack__ manuell mit python licht.py

    gestartet. Der erste Teil - auslesen und Ausgabe der TSL2561 Werte

    und Zeit - lief normal.

    Aber die Unterschreitung des eingegebenen Schwellenwertes (75)

    wurde nicht angezeigt und die Relais schalteten nicht.

    Allerdings wird die SSH Verbindung mit PuTTY regelmässig durch ein

    timeout beendet. Das konnte tmux bei den Tests meines eigenen

    Scripts nicht verhindern, aber das Script lief weiter - ohne Ausdrucke -

    und die Relais schalteten das Licht wie vorgegeben.

    Das test.py Script funktioniert und die Ausgabe nach einem erneuten

    Start unter /etc/rc.local ergib jetzt 2 Zeilen:

    525 ? S 0:00 python /home/pi/test.py

    786 pts/1 S+ 0:00 grep test.py

    Nach dem Start wird allerdings nichts ausgedruckt und ich habe

    feststellen müssen, dass mein Eintrag für licht.py falsch eingetragen war.

    Ich versuche nochmals einen Autostart meines eigenen Scripts mit

    korrektem Eintrag in /etc/rc.local.

    Da ich so keine Ausgaben erwarten kann werde ich versuchen diese

    in eine Datei zu loggen.

  • Hallo.

    du solltest das Skript von __blackjack__ nicht mit python ... starten sondern mit python3... .

    'python' startet Python2 und das Skript von blackjack ist in Python3 geschrieben. Man sollte auch nichts anderes mehr verwenden.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Hallo,

    wenn du an den Python-Installationen auf deinem Pi nichts geändert hast, dann startest du mit 'python' Python2 und mit 'python3' Python3.

    Wenn du die Datei ausführbar gemacht hast und das Programm mit ./Programmname.py startest, dann wird der Interpreter verwendet, denn du im Shebang angegeben hast. Im Falle von __blackjack__'s Programm wäre das auch Python3.

    Das deine Programme, die nach deiner Aussage, in Python3 geschrieben sind, mit 'python' gestartet werden können kann daran liegen:

    Edit: Und Python 3 tauglich ist das auch nicht denn da stehen ``print``-Anweisungen drin die in Python 3 Funktionsaufrufe sein müssen.

    Also ich würde jetzt mal explizit den Aufruf mit 'python3' starten und dann die Fehlermeldung posten, falls eine kommt. Anders kommen wir hier nicht weiter.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • also es hat sich einiges geklärt:

    1. das Script von __blackjack__ funktioniert doch und zwar mit

    python licht1.py und nicht mitpython3 licht1.py. Wahrscheinlich

    habe ich es beim ersten Test zu spät gestartet:

    Es besteht noch das Problem mit dem Verhältnis der beiden Parameter

    Tageszeit (fix) und Licht-Schwellenwert (variabel, abhängig von den Jahreszeiten

    und Wetter), das ich noch lösen muss.

    2. Eine Script Aktivierung unter /etc/rc.local funktioniert definitiv nicht,

    weder nach reboot noch nach shutdown now (und Aus- und Einschalten

    des RPi).

    Ich muss also eine service unit in systemd erstellen.

  • Hallo

    Wie kle schon schrieb die rc.local ist ein Relikt.

    Zum Test habe ich die test.py von hyle in einen Service gepackt und mit einem Timer gestartet.

    Der Name von Service und Timer müssen gleich sein. Nach einem Reboot startet der Timer nach 40 Sekunden den Service.

    Alles läuft, damit ist ein Autostart Deiner *.py wieder möglich.

    Die Datei rc_new.timer

    Code
    [Unit]
    Description=Start vom rc_new.service - Hyle test.py Script.
    
    [Timer]
    OnBootSec=40sec
    Persistent=true
    
    [Install]
    WantedBy=timers.target

    Die Datei rc_new.service

    Einrichtung.

    Code
    sudo cp test.py /usr/local/bin/
    sudo cp rc_new.timer /etc/systemd/system/
    sudo cp rc_new.service /etc/systemd/system/

    Kontrolle und Abfragen vor dem Einschalten des Timers und ein Programm Test.

    Code
    ls -la /usr/local/bin/
        -rw-r--r--  1 root root  290 Apr 25 16:57 test.py
    ls -la /etc/systemd/system/
        -rw-r--r--  1 root root  264 Apr 25 16:57 rc_new.service
        -rw-r--r--  1 root root  142 Apr 25 16:57 rc_new.timer
    /usr/bin/python3 test.py
        test 83
        ^C    Abbruch
            Bye!

    Einschalten des Timers.

    Code
    sudo systemctl enable --now rc_new.timer
        Created symlink /etc/systemd/system/timers.target.wants/rc_new.timer -> /etc/systemd/system/rc_new.timer.
    systemctl reboot                            # Das geht auch als user pi

    Kontrolle und Abfragen nach dem Reboot.

    Bei Änderungen des Service warum auch immer, kann mit dem folgenden Kommando der Service sofort wieder aktiviert werden.

    Code
    sudo nano /etc/systemd/system/rc_new.service
    sudo systemctl reenable --now rc_new.timer
        Removed /etc/systemd/system/timers.target.wants/rc_new.timer.
        Created symlink /etc/systemd/system/timers.target.wants/rc_new.timer -> /etc/systemd/system/rc_new.timer.

Jetzt mitmachen!

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