Bash-Skript läuft aus Crontab nicht richtig :-(

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

    Ich bin am verzweifeln. Habe jetzt Tage damit verbracht einen internen watchdog zum laufen zu bringen und natürlich auch viel Zeit mit suchen in Foren verbracht aber bin nicht zum Ziel gekommen. Dabei nahm ich die Vorlage von meigrafd aus Prozess/Anwendung überwachen.

    Ich frage also ab ob der Prozess noch läuft, wenn nicht starte ich ihn neu und schreibe eine Notiz dazu in eine log-Datei. Läuft so weit auch alles supi(!), aber eben nur wenn ich das aus der Konsole heraus starte/aufrufe. Wenn ich es aber aus sudo crontab heraus starten will, dann wird nur der Prozess neu gestartet (also schonmal ein Teilerfolg und damit Ausschluss so einiger möglicher Fehler).

    Ich hab schon alles versucht, sudo chmod 777, habe versucht es aus der normalen crontab zu starten oder auch aus der /etc/init.d crontab, keine Chance. Habe ein C++ Skript geschrieben, dass das andere Skript einfach nur aufruft, nix... Ich habe auch versucht den Pfad zu ändern, nix... Die log-Datei liegt auch im Ordner in dem das Skript liegt etc etc etc...

    Die Gesamtanwendung ist recht komplex und teilt sich auf mehrere Dateien auf. Hier aber mal das worums geht:

    Wie gesagt, wenn ich aus der Konsole heraus das Programm starte funktioniert alles super. Aus sudo crontab heraus aber nicht. Andere, ähnliche Anwendungen laufen aus sudo crontab heraus aber wunderbar.

    Kann mir jemand weiterhelfen?
    LG, Stefan

  • Bitte absolute Pfade benutzen! Wo soll das watchdog.log liegen :s

    Und was sollen die ganzen sudo's in dem Script?

    Und wie sieht der genaue Aufruf zum eintragen in die Crontab aus? Und letztlich auch: Wie sieht der Crontabeintrag aus

  • Hallo meigrafd :)

    watchdog.log liegt im gleicher Ordner wie darkicewd (das bash Skript). Wenn ich es manuell ausführe, dann wird auch wie gewünscht der Text ins die Logdatei geschrieben, also nahm ich an dass es nicht an der Angabe des Pfades liegt.

    Beide Dateien liegen in /home/pi/gpioexp und natürlich hatte ich auch schon den kompletten Pfad angegeben, also

    Code
    sudo echo "[$(date +"%Y-%m-%d %H:%M")]    Darkice wurde neu gestartet" >> /home/pi/gpioexp/watchdog.log


    Das hat aber keinen Unterschied gemacht :(

    Die ganzen sudos habe ich vorsichtshalber noch dazu geschrieben. Dachte das kann nicht schaden. Hat aber keinen Unterschied bewirkt. Zuvor hatte ich es natürlich auch ohne sudo getestet, ohne Erfolg.

    Der relevante Eintrag in der sudo crontab sieht so aus:

    Code
    #Bei Neustart den RX einschalten und Darkice starten
    @reboot /home/pi/gpioexp/RX_ON


    Dabei wird also RX_ON gestartet, was zunächst ein C++ Skript startet. In dem steht dann wiederum (Ausschnitt)

    Code
    while(1)
    {
    delay(60000); //Jede Minute prüfen ob Prozess noch läuft.  Wenn nicht dann Neustart.
    
    
    system("sudo ./darkicewd_run"); //Darkice Watchdog
    system("sudo bash test");
    }


    Ein Empfänger wird in diesem Skript (weiter oben) per GPIO eingeschaltet. Ich verwende dazu wiringPi.
    Diese Datei wird also beim booten von crontab ausgeführt. Der Empfänger startet und das Programm Darkice auch (ein web Radio Streaming Programm, dass den Ton des Empfängers streamt).
    Weil es einfach nicht funktionieren wollte, dass das darkicewd bash Skript in die Log-Datei schreibt (wenn von crontab aufgerufen) habe ich rumexperimentiert (ich hatte vor 3 Monaten übrigens noch nie etwas mit Linux oder Raspberry zutun) habe ich erst noch ein C++ Skript (darkicewd_run) geschrieben (was ich testweise mal separat aus crontab ausgeführt hatte, ebenfalls ohne Erfolg) was darkicewd (das bash Skript) aufrufen soll. Sehr umständlich und wohl auch nicht nötig aber ich wollte eben einfach, dass die *** Anwendung funktioniert...
    In darkicewd_run steht einfach nur

    Du wirst dir sicher zurecht denken "Nein, wie sinnlos, was für ein Aufwand, mach doch einfach SO!". Aber wenn man die Lösung nicht hat muss man eben rumprobieren mit dem was man halbwegs kann. Interpretiere es als zielstrebige Hartnäckigkeit! ;)

    Ich hoffe du siehst jetzt meinen Fehler (?)

    Einmal editiert, zuletzt von Stef7 (23. März 2015 um 19:37)

  • Da du über Crontab auch den absoluten Pfad zum Script angeben musst, musst du das auch für die Logdatei.

    Wenn Crontab es nicht ausführt dann prüfe /var/log/syslog

    Und wie gesagt, wie du den Crontabeintrag gemacht hast und wie dieser aussieht, frage ich schon mal...

  • ...Also wenn ich mit

    Code
    ps -A

    die laufenden Prozesse nach dem booten anzeigen lasse, dann sehe ich, dass RX_ON läuft. Ausserdem ist der Empfänger eingeschaltet und Darkice läuft auch. Also alles bestens! Die noch so umständlichen Programme werden ausgeführt, nur wird eben kein Eintrag in die watchdog.log ausgeführt.
    Der Eintrag "Kein Neustart erforderlich" (natürlich auch nur zu Testzwecken in dem Skript) sollte ja jede Minute erfolgen.
    Ich habe jetzt nochmal das bash Skript geändert, die sudo's rausgeschmissen und den kompletten Pfad angegeben, also jetzt /home/pi/gpioexp/watchdog.log
    Auch die C++ Datei die den einen GPIO Pin einschaltet ruft jetzt direkt das bash Skript auf, ist sinnvoller ;-).
    Und so brauche ich auch in der crontab nichts zu ändern...

    Jetzt, neu gebootet, ps -A, RX_ON und Darkice läuft, wie gewünscht aber: Kein minütlicher Eintrag in watchdog.log :(
    Wenn ich dann den Prozess Darkice kille wird er wie gewünscht neu gestartet aber: Kein Eintrag ins log :(

    Ich habe der Datei watchdog.log übrigens auch Rechte mit sudo chmod 777 gegeben. Aber das ändert auch nix...

    Hast du noch Ideen? :)

  • Hm, ich dachte ich hätte die Fargen jetzt beantwortet. Den Eintrag in der crontab sieht man ja oben in meiner editierten älteren Nachricht. Du hast noch gefragt wie ich die crontab aufrufe. Naja, mit

    Code
    sudo crontab -e

    , deswegen nannte ich es "sudo crontab".
    Bin gespannt :)

  • OK, hier nochmal der aktuelle Ablauf:
    Ich starte den Raspi.
    Die cron Jobs werden ausgeführt (die, die ich mit "sudo crontab -e" in die crontab von root eingetragen habe).Eintrag:

    Code
    #Bei Neustart den RX einschalten und Darkice starten
    @reboot /home/pi/gpioexp/RX_ON


    Das C++ Skript RX_ON wird ausgeführt. Soweit läuft das ja auch alles!

    Darin wird ein GPIO Pin als Ausgang definiert und H geschaltet sowie das Programm Darkice (https://stmllr.net/blog/live-mp3-…n-raspberry-pi/) gestartet. Das läuft ja auch alles.

    Zusätzlich wird dann jede Minute das bash Skript darkicewd ausgeführt, was jetzt folgendes beinhaltet:

    So weit so gut, läuft. Sinn der Sache ist ja der interne watchdog, also wenn der Prozess Darkice abstürzt soll er eben neu gestartet werden und der Neustart in watchdog.log notiert werden.
    Wenn ich nun, testweise, manuell den Prozess Darkice kille dann wird er tatsächlich wieder neu gestartet. D.h. das bash Skript wird tatsächlich aufgerufen, ausgeführt und auch die Zeile "sudo darkice" erfolgreich ausgeführt. Insofern kann ja schonmal nicht alles total falsch sein.
    Nur wird eben nichts in die watchdog.log eingetragen!

    Und jetzt noch: Wenn ich den Prozess RX_ON kille und ihn dann aus der Konsole manuell wieder starte, dann wird nicht nur wie gewünscht der Pin auf H gesetzt und Darkice gestartet sondern plötzlich wird auch in die watchdog.log eingetragen, also alles wunderbar! Nur funktioniert das eben aus der crontab von root nicht. :s
    Soweit sollte das Problem nur klar beschrieben sein.
    Ich dachte mal es liegt am Pfad und hatte statt "watchdog.log" natürlich längst getestet ob "/home/pi/gpioexp/watchdog.log" einen Unterschied macht. Hat es aber nicht :@

    Sieht jemand den Fehler?

    Einmal editiert, zuletzt von Stef7 (23. März 2015 um 21:01)

  • Ich sehe viele Fehler:

    * Dein crontab Eintrag ist "falsch" bzw. läuft nur nach einem Reboot.

    * Das C-Programm brauchst du nicht, ist irgendwie "von hinten durch die Brust ins Auge": crontab ist dafür da, regelmäßg wiederkehrende Jobs auszuführen, kleinster Abstand ist 1 min.
    Wenn du mehrere Jobs ausführen willst, dann für jeden Job einen eigenen Eintrag in die crontab.

    * Die durch crontab aufgerufenen Programme/Scripte laufen mit root Rechte, "sudo" ist also komplett überflüssig.

    * Die durch crontab aufgerufenen Programme/Scripte laufen in einer eigenen, stark reduzierten Umgebung (Environment). Du musst alles (also auch jeden Kommandoaufruf) komplett mit Pfad zu dem Kommandifile angeben (dein pgrep hat das nicht z.B., "date" auch nicht; selbst den echo Aufruf versehe ich zur Sicherheit damit ("/bin/echo")


    cu., das Zen

  • Hi,

    Also der crontab Eintrag stimmt schon. Mit @reboot wird der Job einmalig beim Systemstart ausgeführt. :)

    Ich glaube aber auch das das Problem der fehlende absoulte Pfad ist. Ich habe mal was ähnliches mit der /etc/rc.local erlebt.

    Er schreibt ja das "Watchdog Skript" funktioniert wie gewünscht und wird auch gestartet, nur das echo scheint nicht zu klappen. Irgendwie komisch das pgrep funktioniert.


    Also Stef7: sudo weg und mal testweise Absolute Pfade verwenden. :)

    Grüße,
    Joh

    DON'T PANIC!

    Einmal editiert, zuletzt von joh.raspi (24. März 2015 um 00:04)


  • Also der crontab Eintrag stimmt schon. Mit @reboot wird der Job einmalig beim Systemstart ausgeführt. :)

    Ja, schon klar... hab ich ja geschrieben... :D

    Aber das ist doch irgendwie daneben: Da wird ein C Prog. gestartet, um das zu tun, was crontab macht. :s

    Wenn das C Prog. abschmiert, geht nix mehr...

    KISS: "Keep it Simple and Stupid" sollte m.M. nach der oberste Grundsatz sein.
    So wenig wie möglich "selbst" machen bzw. mache nix, was das OS nicht auch (besser?) kann... ;)

    cu. das Zen

  • Danke soweit für die Anregungen:thumbs1:


    Also Stef7: sudo weg und mal testweise Absolute Pfade verwenden. :)

    Welches sudo meinst du jetzt? Das in dem bash Skript vor "darkice"? Genau diese Zeile funktioniert aber exakt wie gewünscht. Das einzige Problem ist das Schreiben in watchdoh.log.

    Und was genau meinst du mit absolute Pfade? Ich frage nur damit ich dich nicht evtl. missverstehe. Ich würde jetzt meinen du meinst damit /home/pi/gpioexp/watchdog.log anstatt nur watchdog.log. Aber das mache ich ja schon und es macht keinen Unterschied.

    Ich habe auch ausprobiert vor echo ein /bin/ zu schreiben. Macht auch keinen Unterschied.

    Wie gesagt, das Skript wird (durch crontab) (indirekt, über das C++ Skript) korrekt aufgerufen und ruft auch das Programm darkice auf wenn es abgestürzt ist, nur der Eintrag in watchdog.log funktioniert nicht.
    Wenn ich

    Code
    bash darkicewd

    in der Konsole eingebe (wenn ich im Ordner /home/pi/gpioexp bin, wo es liegt), dann wird alles korrekt ausgeführt.
    Demnach muss es doch irgendwie mit dem Pfad zutun haben der in der echo-Zeile aufgerufen wird.

    Ich versuche mal weiter. Vielleicht hat ja noch jemand eine Idee?

    Die gesamte Struktur mag umständlich sein und hier und da kann auch ein sudo weg und ich brauche sicher auch nicht überall chmod 777. Aber solange es nur um Kosmetik geht möchte ich das jetzt erstmal ignorieren und mich rein auf den entscheidenden Fehler konzentrieren.

    • Offizieller Beitrag

    Da du nicht weisst ob die PATH Varibale zum ausführzeitpunkt schon gefüllt ist brauchst du Absolute Pfade, und zwar überall ;)
    (wenn du das in die crontab von root einträgst brauchst auch kein sudo, wie bereit erwähnt).

  • Danke dbv für deinen Vorschlag. Wow, jetzt kommen wirklich alle Experten hier an den Start. Ich dachte "jetzt muss es funktionieren". Habe die Änderungen eingebaut und neu gestartet, dann den Prozess darkice gekillt. Er wird, wie auch vorher schon, durch das Skript neu gestartet, nach spätestens einer Minute. Aber in der watchdog.log tut sich immer noch nichts:(
    Der manuelle Test aus der Konsole heraus funktioniert, wie auch vorher schon.
    Also keine Änderung im Vergleich zu vorher, das Problem besteht weiter:neutral:

    Könnte es am Einzug der Zeilen liegen, also ob ich mehrmals space oder einmal Tab drücke? Spielt das bei bash eine Rolle? Kann mir aber nicht vorstellen, dass das den Unterschied ausmachen soll warum es aus der Konsole geht und aus crontab nicht...

    Noch Ideen?

    Ich habe auch mal das bash Skript vereinfacht und den ganzen pgrep-Kram rausgelöscht und nur noch

    Bash
    #!/bin/bash
    
    
    /bin/echo "Kein Neustart erforderlich" >> /home/pi/gpioexp/watchdog.log
    
    
    exit 0


    drinstehen lassen. Das Problem besteht weiter!!!

    So langsam habe ich das C++ Programm im Verdacht, welches mittels

    Code
    while(1)
    {
    delay(60000); //Jede Minute prüfen ob Prozess noch läuft.  Wenn nicht dann Neustart.
    
    
    system("sudo bash darkicewd"); //Darkice Watchdog
    
    
    }


    das bash-Skript aufruft. Vielleicht gibt es da spezielle Besonderheiten :thumbs1:

    Ich teste weiter...
    Danke für die Diskussion. Alleine das Formulieren des Problems macht die Sache überschaubarer :thumbs1:

    Jetzt habe ich testweise das bash Skript darkicewd einfach minütlich durch sudo crontab auführen lassen:

    Code
    #Testweise das bash skript minütlich aus sudo-crontab aufrufen
    */1 * * * *    bash /home/pi/gpioexp/darkicewd


    Und das funktioniert jetzt, also Neustart von darkice und Eintrag in watchdog.log! :)
    Ich habe das Skript auch wieder vereinfacht und die absoluten Pfade teilweise weggelassen:

    Auch das funktioniert wunderbar!!! :)

    Jetzt habe ich also die Zeile im C++ Programm schwer im Verdacht, also

    Code
    system("sudo bash darkicewd");


    Werde nun versuchen hier Alternativen zu finden.
    In einer anderen Anwendung, nämlich dem bekannten Projekt "shutdown button für den Raspi via GPIO Pin" verwende ich ja ein ähnliches Skript mit diesem Befehl, in dem Fall

    Code
    system("sudo shutdown -h now");

    und da gab es nie Probleme!...
    Ich werde dann die funktionierende Lösung hier darstellen.

    Einmal editiert, zuletzt von Stef7 (24. März 2015 um 13:56)


  • darkicewd ist dann das bash script?


    Ja.


    Und das C-Programm wird per cron aufgerufen? Absolute Pfade gilt übrigens auch für C-Script ;) )


    Ja. Das C++-Programm soll und wird auch per cron aufgerufen. Ich habe es auch mit absoluten Pfaden versucht, also

    Code
    system("sudo bash /home/pi/gpioexp/darkicewd"); //Darkice Watchdog


    ...macht aber auch keinen Unterschied.
    Vielleicht sollte ich lernen die ganze Aufgabenstellung in bash zu realisieren, nicht in C++ und bash kombiniert. Scheint ja echt an dem Befehl "system ("...");" zu liegen. Bin halt sehr hartnäckig was das angeht...
    Ich werd's noch weiter versuchen wie ich mich kenne ;)


  • Wenn das C Programm in der crontab von root steht, brauchst du das sudo nicht.

    Ich habe halt wie gesagt bis vor 3 Monaten noch nie was mit Linux zutun gehabt. Sudo? Wat soll dat denn sein? ...hätte ich da gefragt... Python? Häää?

    Vor einem halben Jahr hab ich dann mit Arduinos begonnen und hatte daher etwas "Ahnung" von C++, habe deswegen auch wiringPi verwendet. Das Skript für den shutdown button funktioniert wunderbar, also auch der Befehl "System();".
    Was bash sein soll wusste ich bis vor wenigen Wochen noch nicht. Und wenn ich eine funktionierende Vorlage in C++ habe und von bash noch null Ahnung, dann ist es doch nachvollziehbar dass ich es damit versuche (?).
    Ich brauchte dann die Möglichkeit abzufragen ob ein Prozess noch läuft und auf der Suche nach Lösungen dafür bin ich dann auf diesen Eintrag gestoßen: Prozess/Anwendung überwachen
    Also hatte ich nun die Vorlage in bash, die ich abgeändet habe und einfach in das bereits existierende C++ Skript eingebaut bzw. sie daraus aufgerufen habe.
    Hat ja auch ein ganzes Stück weit funktioniert, darkice wird neu gestartet. Also dachte ich liegt nur irgendwo noch ein kleiner Fehler, etwa die Pfadangabe und hier und da noch ein sudo hin oder weg und dann bin ich am Ziel. An der Stelle würde ich doch nicht anfangen erst bash von grund auf zu lernen oder am besten gleich python. Da wird es auch einige geben die sagen "Mach's doch in python, das ist viel einfacher"...

    Letztlich liegt aktuell in meinem Programm ein Fehler und den will ich finden. Und der Fehler ist wohl nicht ein sudo was irgendwo zu viel steht...

    LG...

    • Offizieller Beitrag

    Un ob das ein mögliche Fehlerquelle sein kann. Beispiel gefällig von meinen Debian Server?

    Code
    user@NAS sudo
    bash: sudo: Kommando nicht gefunden.

    Deswegen macht es sinn zu wissen wer, was mit welchen Rechten ausführt.

    Zitat von man sudo


    execute a command as another user


    Wenn das Script von Root ausführt wird, als welcher User soll er es denn starten ;)


    Hier mal die Version absoluten Pfaden überall

    Code
    system("/usr/sbin/sudo /bin/bash /home/pi/gpioexp/darkicewd"); //Darkice Watchdog

Jetzt mitmachen!

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