rc.local verhällt sich seltsam

  • Hallo zusammen

    ich hab seit Tagen ein Problem mit meinem Pi und werd allein nicht schlau draus...

    Ich starte über die "rc.local" das script "/root/autostart.sh".
    hier steht alles drin, was ich beim hochfahren des systems benötige.
    funktioniert soweit auch - bedingt.

    Alle Scripte die eine reine Ablaufsteuerung sind werden korrekt bearbeitet und auch beendet.
    Scripte die einen Schleifenprozess erzeugen (natürlich mit '&', bevor gleich einer schreit) werden ausgeführt (ich sehe sie im "ps x"), aber reagieren nicht....

    Mein Problem im speziellen:
    ich starte ein pythonscript, das GPIO-Eingänge überwacht. es erscheint in der Prozessliste, aber reagiert nicht.
    starte ich es manuell über die selbe autostartdatei, beschwert sich python, dass es bereits läuft, aber danach reagiert es.

    WARUM?!?!? :)

  • Bitte Zeige den exakten Eintrag in /etc/rc.local (am besten die ganze Datei) sowie das vollständige Script "/root/autostart.sh" und alle von deinem Problem betroffenen anderen Scripts

  • rc.local:

    Bash
    #!/bin/sh -e
    
    
    /bin/sh /root/autostart.sh
    
    
    exit 0
    
    
    #------EOF-----


    autostart.sh:

    Bash
    #!/bin/sh
    
    
    /bin/sh /root/led0_heartbeat.sh &
    
    
    /usr/bin/python /root/test_taster.py &
    
    
    #------EOF-----


    led0_heartbeat.sh:

    Bash
    #!/bin/sh
    
    
    echo "heartbeat" >/sys/class/leds/led0/trigger
    
    
    #------EOF-----


    test_taster.py:


    Ich habe schon häufiger gelesen, dass es Probleme mit scripten im rc.local gibt.
    keiner hat bis jetzt aber erwähnt, dass "schleifen-programme" nicht funktionieren, stupide "Ablaufsteuerungen" jedoch ohne Probleme.
    Gibt es einen Mechanismus im Betriebssystem, der Tasks abbricht die im rc.local stehn ?

    es gibt ja alternativen wie init.d, cron uvm...

    wo liegt der unterschied zwischen den Varianten?

    Einmal editiert, zuletzt von pi_maniac (26. Januar 2015 um 13:10)

  • Fürs nächste mal: Bitte in CODE posten

    Generell:
    /etc/rc.local wird als root am Ende es Bootvorgangs ausgeführt und somit auch alle darin befindlichen Befehle. Ein erneuter Aufruf von sudo ist also i.d.R. überflüssig.
    Angewöhnen vollständige/absolute Pfade zu verwenden, auch für die Interpreter sh/bash/python. Wo diese liegen findet man mit which sh usw heraus.
    sh ist veraltet, es sollte vorzugsweise bash genutzt werden. Die Dateiendung ".sh" sagt nichts über den Interpreter aus.

    Zu /etc/rc.local:
    Bitte hinter deiner Zeile ein " & " einfügen:

    Code
    sh /root/autostart.sh &

    Zu /root/autostart.sh:
    Der 2. Eintrag wird solange nicht ausgeführt bis der erste Eintrag beendet wurde. Wenn das aber sein soll dann auch hier ein & ans Ende der Zeile:

    Code
    sh /root/led0_heartbeat.sh &
    
    
    python /root/test_taster.py &

    Zu /root/test_taster.py:
    Ich vermisse ein GPIO.cleanup()
    Die verschachtelten while Schleifen werden sich stören und Kern deines Problems sein.
    So wie ich das sehe wärst du mit Interrupts besser dran:

    Spoiler anzeigen

    [code=php]#!/usr/bin/python
    # -*- coding: utf-8 -*-
    #
    # Interrupt löst ungewünscht aus
    # [Python] Hilfe bei Python script für Drehzahlmesser mit IR lichtschranke
    # Auf Flanken reagieren und mehrer Befehle ausführen
    #
    import RPi.GPIO as GPIO
    import time
    import signal

    gpioPin1 = 5
    gpioPin2 = 38
    gpioPin3 = 40

    #GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(gpioPin1, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
    GPIO.setup(gpioPin2, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
    GPIO.setup(gpioPin3, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

    def Interrupt_event(pin):
    timeNow = time.asctime()
    print("{} -> GPIO {} ausgeloest!".format(timeNow, pin))

    try:
    GPIO.add_event_detect(gpioPin1, GPIO.RISING, callback=Interrupt_event, bouncetime=150)
    GPIO.add_event_detect(gpioPin2, GPIO.RISING, callback=Interrupt_event, bouncetime=150)
    GPIO.add_event_detect(gpioPin3, GPIO.RISING, callback=Interrupt_event, bouncetime=150)
    #keep script running
    signal.pause()
    except KeyboardInterrupt:
    print("\nQuit\n")

    GPIO.cleanup()[/php]

    wo liegt der unterschied zwischen den Varianten?

    Forumsuche nach: Autostart
    Bzw hier lesen: Automatisches Starten von Scripte / Programme ( Autostart )

  • Holla, DAS ging aber echt flott!
    Danke dafür schonmal! :thumbs1:

    Ich hab nun überall die Pfade ergänzt und auch die "&".
    Keine Änderung.

    Was genau macht "GPIO.cleanup()"?
    benötige ich das, wenn ich gar nicht vor habe, das Programm zu verlassen?

    Die Änderung im Code auf die Interrupts leuchtet mir jedoch nicht ein, da der Code ja funktioniert, wenn ich ihn selbst starte...

    Die Frage ist vllt untergegangen:

    Warum sehe ich den Task als gestartet im "ps x", reagiert jedoch nicht wenn er durch rc.local gestartet wurde?

    Einmal editiert, zuletzt von pi_maniac (26. Januar 2015 um 12:49)

  • Entweder weil das Script fehlerhaft ist, oder weil zu dem Zeitpunkt als es gestartet wurde noch kein GPIO ansprechbar war (auch dann wäre das Script fehlerhaft da es das nicht berücksichtigt :D)

    Zum Thema "Wann Was" ausgeführt wird, hab ich mal einen kleinen Test gemacht um das zu demonstrieren.

    Test-Script erstellt: nano /root/TEST.sh

    Code
    TEXT="$(/bin/date) --> $1 as $(whoami)"
    (/bin/echo 17 > /sys/class/gpio/export) >> /root/log.TEST 2>&1
    sleep 1
    [ ! -z "$(/bin/ls /sys/class/gpio/gpio17/)" ] && TEXT+=" GPIO"
    sleep 1
    echo 17 > /sys/class/gpio/unexport >/dev/null 2>&1
    sleep 1
    /bin/echo $TEXT >> /root/log.TEST
    /bin/echo "---" >> /root/log.TEST

    (lass dich vom sleep nicht störn, die Zeit vom ausführen wurde zu dem Zeitpunkt bereits in die Variable TEXT geschrieben)

    Dann in verschiedene "Autostart" Möglichkeiten eingetragen:

    • /etc/rc.local
      Bash
      #!/bin/sh
      
      
      /bin/bash /root/TEST.sh '/etc/rc.local' &
      
      
      exit 0
    • /etc/crontab
      Code
      @reboot root /bin/bash /root/TEST.sh '/etc/crontab'
    • sudo crontab -e
      Code
      @reboot /bin/bash /root/TEST.sh 'sudo crontab -e'


    ...Und dann natürlich rebootet...
    Anschließend cat /root/log.TEST

    Code
    /bin/echo: Schreibfehler: Das Gerät oder die Ressource ist belegt
    Do 1. Jan 01:00:22 CET 1970 --> /etc/crontab as root GPIO
    Do 1. Jan 01:00:22 CET 1970 --> sudo crontab -e as root GPIO
    ---
    ---
    /bin/echo: write error: Device or resource busy
    Mon Jan 26 15:23:31 CET 2015 --> /etc/rc.local as root GPIO
    ---

    Zu dem Zeitpunkt wo es über die Crontabs ausgeführt wurde, war noch keine Zeit gesetzt da der PI ja keine RTC hat... Beide wurden aber Zeitgleich ausgeführt.

    Was aber ist mit GPIO? Tja, Gute Frage nächste Frage :auslachen: Obwohl ich dem ja durch die sleeps Zeit gegeben habe bis die Befehle "gewirkt" haben, sollte es zumindest funktioniert haben - hat es auch irgendwie denn /sys/class/gpio/gpio17/ existiert, dürfte es aber eigentlich da ich den gpio ja auch wieder unexportet hab :wallbash:
    Was lern wir daraus? Alle Möglichkeiten ausprobieren!:angel:

  • Ui, hab ich im ersten Post nicht geschrieben:
    Ich hatte gestern auch schon mal probiert, das python-script mit 60 Sekunden Verzögerung zu starten, jedoch selbes Resultat.
    Die kleinen Scripte wurden anstandslos abgearbeitet, Schleifen-Programme nicht.
    Ich habe wirklich die Befürchtung, dass hier ein Wirkzusamenhang mit dem OS besteht. :(

    Einmal editiert, zuletzt von pi_maniac (26. Januar 2015 um 15:38)

  • Nein.

    Wenn ich das korrekt verstanden habe, ist "crontab" wie eine Zeitschaltuhr.
    Das ist für mich der falsche Anwendungszweck.

    Meine Programme müssen direkt nach dem Hochfahren einmal gestartet werden und dann permanent laufen, bis der Controller von außen ein Stop-Signal bekommt (via GPIO).

    Oder kann ich "crontab" für eine Einmalige Aktion 'missbrauchen'?

  • @reboot in crontab:
    Worauf triggert diese Funktion?
    auf die Eingabe von "reboot" oder auch wenn er aus dem halt 'aufgeweckt' wird?

    Interessehalber:
    Einfach so am ende der Datei eingeben?
    Im Moment ist meine crontab leer (bis auf die Kommentarzeilen)


    Ich benötige einen sicheren Weg die Scripte zu laden für folgende Fälle:
    - Hochfahren nach Spannungsverlust (Versagen der USV)
    - Aufwecken über P5 (SCL) aus dem 'shutdown -h' heraus

    Einmal editiert, zuletzt von pi_maniac (26. Januar 2015 um 16:26)

  • @reboot ist eine Sonderfunktion und wird beim Systemstart beachtet, sobald CRON gestartet ist.... Das siehst du aber doch an meinem TEST-Beitrag :huh:


    Wie gesagt: Ausprobieren!

  • Ich bin ja ma wieder etwas dumm was python angeht, aber woran machst du fest, dass dein Skript reagiert? Daran, das der print Befehl ausgegeben wird? Wie gesagt ich habe keine Ahnung von Python, aber ich sehe nicht wohin dein Skript den print schreiben soll.
    Ein Skript was bei Systemstart, wie auch immer gestartet wird, schreibt nicht in deine terminal, wenn man es nict explizit einbaut.

    --
    man ist das System-Anzeigeprogramm für die Handbuchseiten von Linux.

  • @ meigrafd
    Bin noch nicht zum testen gekommen, sorry.
    Folgt jetzt :)

    Zum Cron-Tutorial:
    ich vertseh grad 2) und 3) nicht.
    Gibt es mehrere crontabs?
    für mich sihts auf den ersten blick aus wie 2 mal in die gleiche Datei eintragen.


    @ Lunepi:
    Ich sehe es daran, das A der Text im Terminal angezeigt wird, und B dass die Routinen die ich dort für die anderen Taster starte auch gestartet werden, wenn ich den Taster drücke. Der Code ist etwas gekürzt, der übersicht halber. das Gerüßt ist jedoch unverändert.

    Wie bereits erwähnt: Ich versuche zu verstehen, warum der Aufruf der autostart.sh variiert, jenachdem ob sie über den PI oder von MIR gestartet wird.

  • Achte auf's " wo " 2) & 3) eingesetzt wird... Ja das sind 2 verschiedene, sonst würds da nicht stehn... zumal da auch extra bei einem steht das das eine ne Spalte mehr hat usw - alles Indizien die für 2 verschiedene Varianten sprechen


  • @ Lunepi:
    Ich sehe es daran, das A der Text im Terminal angezeigt wird

    Wie gesagt, das wird nicht funktionieren - Es gibt keine Terminal bei Skripten die nicht in einem Terminal gestartet werden, dass ist bei rc.local der Fall. Bei deinem 1. Skript leitest du das echo in eine Datei um, das geht! nicht aber eine einfache print ( geht auch du wirst es nur nie sehen )


    Wie bereits erwähnt: Ich versuche zu verstehen, warum der Aufruf der autostart.sh variiert, jenachdem ob sie über den PI oder von MIR gestartet wird.

    - kein Terminal
    - keine Umgebungsvariablen (PATH, etc)
    - evtl. andere rechte
    - falscher Startzeitpunkt ( das vor dem oder andersrum )

    --
    man ist das System-Anzeigeprogramm für die Handbuchseiten von Linux.

  • :D:lol::bravo2::lol::D
    Viiiiiiieeeeeeeeeeeeeeeelen DANK meigrafd !!!!!

    Code
    nano /etc/crontab
    
    
    @reboot root /usr/bin/python /root/test_taster.py '/etc/crontab'

    Hat auf anhieb funktioniert! :danke_ATDE:


    Was nun dennoch dir Frage offen läßt: Warum? Denn der Code ist weiterhin unverändert ;)

  • Code
    @reboot root /usr/bin/python /root/test_taster.py '/etc/crontab'

    Das Argument brauchst du nicht - das war nur Bestandteil meines Tests. Das reicht:

    Code
    @reboot root /usr/bin/python /root/test_taster.py

    Was nun dennoch dir Frage offen läßt: Warum? Denn der Code ist weiterhin unverändert ;)

    Vermutlich aus den Gründen die Lunepi genannt hat:

    Du verwendest nun /etc/crontab , wo festgelegt wird über welchen Benutzer der Befehl ausgeführt werden soll. Über diesen Benutzer existieren Umgebungsvariablen usw, was bei /etc/rc.local nicht der Fall ist.
    'crontab -e' ist die Benutzer-Crontab, die dann selbstverständlich ebenfalls Umgebungsvariablen usw besitzt.

    But who cares solang es funktioniert :fies:

Jetzt mitmachen!

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