shell script funktioniert nicht per crontab

L I V E Stammtisch ab 20:30 Uhr im Chat
  • Hallo!

    Ich hab mir ein kleines Script gebastelt mitdem ich die Gpios checke und den Status in eine .txt schreibe.
    Wenn ich das Script per bash /root/gpiostate.sh starte funktioniert auch alles einwandfrei.

    Starte ich das Script jedoch per Crontab oder einem anderen Script (watchdog) funktoniert es nicht. ich finde zwar den Prozess aber es wird nichts ausgeführt.

    hab schon alls Files mit chmod 777 "freigegeben".
    die Pfade zu den .txt s sind alle absolut angegeben (/root/IOstate/poollichtstate.txt)

    hier der erste part vom Script (dieser teil wird 4mal mit unterschiedlichen gpios und .txt s wiederholt)


    hoffe ihr könnt mit helfen! ;)

    lg hannes[/align]

    Einmal editiert, zuletzt von hannes_os (13. Juni 2014 um 02:24)

  • Ist der sleep Befehl wirklich in der ersten Zeile? (Oder liegt das an der Tapatalk-Anzeige)
    Wenn ja, ändere dies, also sleep in eine eigene Zeile
    Die erste Zeile signalisiert nur, dass es ein bash-script ist.

  • Moin,

    ich denke diese Zeile wird nicht funktionieren....

    Code
    if [ $(gpio read 1) = 1 ]

    Denn wenn "gpio read 1" 0 raus kommt steht da $0 was entweder versucht wird auszuführen oder (und das vermute ich ) als der aufgerufenen Befehle und der wird dann zurück gegeben.

    Also besser

    Code
    while true 
    do
    $VAR=`gpio read 1`
    
    
    if [.....

    Insofern wundere ich mich, das es angeblich von der Komanndozeile funktioniert, aber so ist es nicht richtig

    Gruß
    Lunepi

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

  • > Denn wenn "gpio read 1" 0 raus kommt steht da $0 was entweder versucht wird
    > auszuführen oder (und das vermute ich ) als der aufgerufenen Befehle und der
    > wird dann zurück gegeben.
    Noeh, das der Befehl wird ausgefuehrt und der Output anstelle von $(...) eingesetzt.

    Das $ verschwindet also bei der ersten Runde.

    Es koennte aber trotzdem an dieser Zeile liegen, weil die Ausfuehrung per cron ein
    anderes Environment hat. Deshalb bei gpio auch den gesamten Pfad angeben.


  • > Denn wenn "gpio read 1" 0 raus kommt steht da $0 was entweder versucht wird
    > auszuführen oder (und das vermute ich ) als der aufgerufenen Befehle und der
    > wird dann zurück gegeben.
    Noeh, das der Befehl wird ausgefuehrt und der Output anstelle von $(...) eingesetzt.

    Das $ verschwindet also bei der ersten Runde.

    Es koennte aber trotzdem an dieser Zeile liegen, weil die Ausfuehrung per cron ein
    anderes Environment hat. Deshalb bei gpio auch den gesamten Pfad angeben.

    Danke für die schnellen Antworten!

    Also wie gesagt, per Terminal funktioniert alles einwandfrei.

    "Deshalb bei gpio auch den gesamten Pfad angeben."

    Wenn ich das Script über ein anderes .sh öffne, also

    Bash
    #!/bin/bash
    
    
    bash /root/gpiostate.sh

    müsste doch genau das gleiche passieren wie wenn ich das ins termial schreibe, oder?

    Wie würde der genaue Pfad zu gpio den lauten? is ja ein command!?

    danke

    mit meinem watchdog funktionierts eben auch nicht... server1.py wird jedoch richtig gestartet...

    kanns auch hier am Pfad liegen?

    Einmal editiert, zuletzt von hannes_os (13. Juni 2014 um 10:38)

  • "für immer".. sollte vermutlich ein & dahinter, oder? :wallbash:

    Gut, hab jetzt den pfad zu gpio angegeben und beim watchdog hinter den bash befehlen ein & gesetzt.
    Läuft jetzt auch soweit, nur dass jetzt gpiostate.sh alle 14sek (sleep vom watchdog) geöffnet wird^^

    Wenn mir hier noch kurz jemand helfen könnte wären all meine Probleme gelöst! ;)

    sehr eigenartig...

    starte ich watchdog.sh per terminal erkennt er dass "gpiostate.sh" läuft und nichts weiter passiert.

    starte ich den watchdog jedoch per rc.local startet er "gpiostate.sh" bei jedem durchlauf erneut, egal ob es bereits läuft oder nicht.
    Meinen watchdog habe ich ja bereits oben gepostet.
    Wäre echt dankbar wenn wird dieses Problem noch lösen könnten!

    danke!

    Einmal editiert, zuletzt von hannes_os (13. Juni 2014 um 11:57)

  • Du startest die Scriots in der Konsole als auch im Crontab als root ?

    Code
    if [ $(gpio read 1) = 1 ]


    Hier vergleichst du ZAHLEN !
    Der korrekte operator für Zahlen ist eq nicht =
    Wenn ich jetzt nicht ganz auf dem holzweg bin setzt du die variable $(gpio read 1) auf 1
    ( Angenommen $(gpio read 1) wäre 0 dann setzt du die Variable 0 auf 1

    Richtig wäre entweder

    Code
    if [ "$(gpio read 1)" == "1" ]


    oder

    Code
    if [ $(gpio read 1) eq 1 ]

    Oder bin ich jetzt im falschen Film ?

    Offizieller Schmier und Schmutzfink des Forum.
    Warum einfach wenn's auch schwer geht ?

    Kein Support per PN !
    Fragen bitte hier im Forum stellen. So hat jeder etwas davon.

  • Mit = kann man auch problemlos Zahlen vergleichen ;)

    == wäre eine genauere Festlegung, aber das einfache = sollte reichen.

    nur "eq" ist aber falsch, es müsste mit vorangestelltem Bindestrich geschrieben werden, also so: -eq

    Ein einfacher Test den ihr selber in der Konsole durchführen könnt:


    Aber da es ja durch manuelle Ausführung laut TE funktioniert muss es imho am Crontab Eintrag liegen - den ich gerne mal sehen würde ;)


    PS: Die standard Konsole ist eine bash shell. Der TE hat aber als Shebang sh angegeben - ggf verursacht auch das Probleme da sh älter als bash ist und nicht so viel kann - im Zweifel einfach immer bash nutzen (abwertskompatibel)

  • Um mal alle Unklarheiten zu beseitigen: ;)

    Das Script läuft jetzt problemlos, sowohl per rc.local als auch per crontab. Das Problem war einfach der fehlende Pfad zu gpio.

    Das script starte ich jetzt aber einfach mit dem ersten durchlauf vom watchdog.
    Mein Problem jetzt:

    Der Watchdog startet das Script bei jedem Durchlauf erneut, obwol der prozess bereits läuft!?

    hier nochmal watchdog.sh (wird per rc.local gestartet)

    hoffe auf einen Tipp! ;)

    cheers

    die ausgabe von

    also auf jedenfall nicht leer ;) trotzdem startet er das script immer wieder.

    Aja, wie oben geschrieben passiert das nur wenn ich watchdog per rc.local oder crontab starte, per Terminal funktioniert alles bestens.

    so, hab jetzt das & nach bash /root/gpiostate.sh gelöscht, bei python /server1.py aber gelassen, und siehe da: ES FUNKTIONIERT :D

    Keine Ahnung warum, aber egal...

    Danke euch vielmals für die Hilfe!!
    Tolles Forum, tolle Leute!

    Einmal editiert, zuletzt von hannes_os (13. Juni 2014 um 16:26)

  • Ein watchdog sollte in die Crontab eingetragen werden, sodass er zB jede Minute oder zB alle 2, 5 oder 10 Minuten ausgeführt wird. Das erspart enorm Systemresourcen da dafür dann kein permanenter Prozess im Hintergrund läuft. So oft sollte es nicht vorkommen dass das Script crasht und watchdog in Aktion treten muss.

    Desweiteren wirst du eine Ausgabe nicht sehen können, wäre also über /etc/rc.local oder crontab hinfällig und sollte in dem Fall nach /dev/null umgeleitet werden:
    /path/to/watchdog.sh >/dev/null 2>&1 &

    Wenn es in crontab eingetragen wird dann & selbstverständlich weg lassen

  • Code
    APP=$(ps aux | grep -v grep | grep server1.py)
    
    
    if [ -z "$APP" ];

    Das geht so nicht denn in $APP steht immer was...

    Mach es besser so:

    Code
    ps aux |  grep server1.py |grep -vq grep 
    
    
    if [ $? -eq 0 ];
    NIX tun
    else
    starten
    fi



    NACHTRAG: Ach hätte ich doch zu ende gelesen... ;) Also vergiss meine Antwort ( wenn ich auch via $? persönlich besser finde...)

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

    Einmal editiert, zuletzt von Lunepi (16. Juni 2014 um 12:49)


  • Mit = kann man auch problemlos Zahlen vergleichen ;)

    == wäre eine genauere Festlegung, aber das einfache = sollte reichen.

    Danke !
    War doch der falsche Film ;)

    Offizieller Schmier und Schmutzfink des Forum.
    Warum einfach wenn's auch schwer geht ?

    Kein Support per PN !
    Fragen bitte hier im Forum stellen. So hat jeder etwas davon.

  • Entschuldigt das ich jetzt ein klein wenig Offtopic werde - aber ich sehe das als nützliche Lextion für den TE ;)

    Code
    APP=$(ps aux | grep -v grep | grep server1.py)
    
    
    if [ -z "$APP" ];

    Das geht so nicht denn in $APP steht immer was...[

    Naja, -z prüft ob die Variable leer ist und das ist hier der Fall sofern das Script nicht läuft ;)
    Auch hierfür ein einfacher Test den ihr in der Konsole ausführen könnt:

    Bei folgendem bemerkt ihr den Umstand den Lunepi vermutlich verwirrt hat:

    Code
    root@raspberrypi:~# APP=$(ps aux | grep -v grep | grep server1.py)
    root@raspberrypi:~# echo a; echo $APP; echo z
    a
    
    
    z

    Da steht ihr "nichts" als Rückgabe. Das nach a eine neue Zeile anfängt ist normal, wer das genauer wissen möchte nutzt einfach "echo -n" um keine newline nach "echo a" zu erzeugen:

    Code
    root@raspberrypi:~# APP=$(ps aux | grep -v grep | grep server1.py)
    root@raspberrypi:~# echo -n a; echo -n $APP; echo z               
    az
    root@raspberrypi:~#

    Und dann der Befehl den der TE nutzt:

    Code
    root@raspberrypi:~# [ -z "$(ps aux | grep -v grep | grep server1.py)" ] && echo jo || echo no 
    jo
    root@raspberrypi:~#


    Da die Rückgabe von der if Abfrage nach -z leer ist wird "jo" ausgeworfen.

    Da die Rückgabe nicht leer ist trifft nicht && zu sondern || .
    Diese Schreibweise mit && entspricht "then" und || entspricht "else" von der if Schleife, nur eben als Einzeiler ;)
    ( && -> UND ... || -> ODER )

    Wenn es aber einen solchen Prozess gäbe würde stattdessen no zurück gegeben, weil das nicht leer ist:

    Code
    root@raspberrypi:~# [ -z "$(ps aux | grep -v grep | grep apache2)" ] && echo jo || echo no             
    no
    root@raspberrypi:~#


    -z bedeutet: leer
    ! -z bedeutet: nicht leer
    -n bedeutet: nicht leer
    ! -n bedeutet: leer



    Mach es besser so:

    Code
    ps aux |  grep server1.py |grep -vq grep 
    
    
    if [ $? -eq 0 ];
    NIX tun
    else
    starten
    fi



    NACHTRAG: Ach hätte ich doch zu ende gelesen... ;) Also vergiss meine Antwort ( wenn ich auch via $? persönlich besser finde...)

    Ich nicht - und sag dir auch wieso:
    $? prüft den Rückgabe-Wert bzw exit-Code / Exitstatus des zuletzt ausgeführten Befehls. 0 entspricht dabei "erfolgreich" und alle Zahlen zwischen 1 bis 255 entsprechen einem Fehler (siehe dazu Exit Codes With Special Meanings)

    Bedeutet:
    $? gibt den Exitstatus des letzten Befehl deiner Pipe aus, in diesem Fall also "grep -vq grep".
    Das "grep" ausgeschlossen sein soll, sollte man deshalb auch immer vor der eigentlichen Suche setzen, also richtiger wäre: ps aux | grep -vq grep | grep server1.py
    Das -q kann man sich bei dem gepipten grep übrigens ebenfalls sparen ;)

    Und zu guter letzt hast du das "then" nach ; vergessen - aber das is vermutlich nur ein Flüchtigkeitsfehler ;)


    Diese Art der Prüfung ( $? ) ist gut für einen eigenen Error-Handler, wenn man den Exitcode verschiedener Befehle/Funktionen prüfen möchte - auch hierfür kann ich euch ein Anschauungsbeispiel geben:

    Zuerst lege ich oben in meinem bash Script eine Funktion fest die je nach übergebenem Exitcode an die Funktion, einen Farbigen Text nach ganz rechts ins Terminal schreibt - entweder FAIL wenn 'grösser 0' also ein Fehler aufgetreten ist oder DONE wenn eine 0 zurückgegeben wurde. Ich prüfe erst auf 'grösser 0' und wenn das der Fall ist wird das Script mit "exit 1" beendet, damit ein anderes Script ggf merkt "da lief was schief" (gut für Verkettungen mehrerer Scripts). $1 ist hierbei das erste Parameter/Argument welches der Function _error übergeben wurde, $2 wäre das zweite usw

    Code
    function _error () {
    	if [ $1 -gt 0 ]; then
    		echo -e "\033[500C\033[8D\033[1;37;40m\0133\033[1;31;40m FAIL \033[1;37;40m\0135\033[0m"
    		echo -e "\t\033[1;31;40mAbbruch\033[0m"
    		exit 1
    	fi
    	echo -e "\033[500C\033[8D\033[1;37;40m\0133\033[1;32;40m DONE \033[1;37;40m\0135\033[0m"
    }

    Lasst euch erstmal nicht von den ganzen Farb- und Formatierungs-Codes irritieren, bei bedarf erklär ich das auch noch mal ;)

    Nun kann ich weiter unten im Script irgendeinen Befehl ausführen und den Exitstatus prüfen, zum Beispiel so:

    Code
    ls -la /
    _error $?


    Da der Befehl erfolgreich war wird mir ein DONE ausgegeben und das Script läuft weiter.
    Führ ich dann aber einen Fehlerhaften Befehl aus:

    Code
    labla
    _error $?


    wird rechts ein FAIL angezeigt und das Script wird beendet

Jetzt mitmachen!

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