Cronjob startet python Skript nicht

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

    ich bin gerade am verzweifeln ein Python Skript während des Starts per Cronjob/Crontab aufzurufen.

    Folgende Heransgehenweiße wurde ausgeübt:

    - Login als Benutzer " pi " über SHH per Terminal
    - cronetab geöffnet:

    Code
    crontab -e


    - und folgenden Code inklusive Leerzeile unten eingegeben:

    Code
    @reboot sudo python /home/pi/programme/Einlesen.py &
    0 0 * * * /home/pi/programme/check.sh

    Das Skript Einlesen.py soll beim hochfahren gestartet werden und das Skript check.sh soll einmal täglich überprüfen ob das Einlese Skript läuft und falls nicht soll es dies Starten. Die Skripte funktionieren. Nur der Cronjob macht mir Schwierigkeiten.

    Die syslog gibt folgendes aus:

    Code
    Jul  3 03:33:59 raspberrypi /usr/sbin/cron[1978]: (CRON) INFO (pidfile fd = 3)
    Jul  3 03:33:59 raspberrypi /usr/sbin/cron[1985]: (CRON) STARTUP (fork ok)
    Jul  3 03:33:59 raspberrypi /usr/sbin/cron[1985]: (CRON) INFO (Running @reboot jobs)
    Jul  3 03:33:59 raspberrypi /USR/SBIN/CRON[1992]: (pi) CMD (sudo python /home/pi/programme/Einlesen.py &)

    es steht zwar da, dass der Befehl ausgeführt wird, jedoch ist das Skript nicht an. Das sehe ich einerseits mit dem "ps -ef | grep Einlesen" Befehl und andererseits daran das keine Daten ankommen.

    Ich starte den Pi in den Kommandozeilenmodus, d.h. ich logge mich auch nicht ein, bzw. logge mich nicht in die GUI ein. Kann hier der Fehler liegen?

  • Hallo Luki,

    du musst bestimmt entweder
    - nicht nur das py-Skript sondern auch den Python-Interpreter starten oder
    - das py-Skript ausführbar machen

    Läuft das py-Skript denn überhaupt als solches?

    Gutes Gelingen!

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    Einmal editiert, zuletzt von Andreas (3. Juli 2014 um 08:15)

  • Andreas ließt du die Beiträge auf die du antwortest eigentlich?
    Die Scripte laufen als solche, das steht deutlich im Beitrag!
    Der Python Interpreter wird aufgerufen, da steht eindeutig
    @reboot sudo python /home/pi/programme/Einlesen.py &
    Das python ist der Pythoninterpreter wie du wissen solltest!
    Andreas Beitrag ist leider völlig wertlos!

    Was das Problem ist, sehe ich jedoch auch nicht, ich würde vermuten es liegt am Inhalt... kommentier mal alles aus und mache nur etwas einfaches was du überprüfen kannst in dem Script (Etwas in eine Datei schreiben oder sowas)

    Daran, dass du die Komandozeile nutzt kann es auch liegen, aber nur wenn dein Script eine GUI hat oder sonst etwas spezielles GUI-Basiertes braucht, generell braucht man keine GUI!

  • Moin,

    @Horror, danke das wir jetzt wissen das Andreas etwas überlesen hat.

    LUKI: beim Ausführen der crontab hat das System nicht die gleichen Infos (ENVIROMENT), wie wenn du dich eingeloggt hast (Stickwort: profile ) d.h. du musst die kompletten Pfade zu sudo und python angeben. Sowohl in der @-Zeile als auch im .sh.
    Ich bin mir unsicher ob es dann funktioniert, denn ein sudo in der cron.... (NUR) gefühlt keine gute Idee, aber ich kann es nicht begründen. Aber versuchs erst mal mit den Pfaden.

    Gruß Lunepi

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


  • Was das Problem ist, sehe ich jedoch auch nicht, ich würde vermuten es liegt am Inhalt... kommentier mal alles aus und mache nur etwas einfaches was du überprüfen kannst in dem Script (Etwas in eine Datei schreiben oder sowas)

    Daran, dass du die Komandozeile nutzt kann es auch liegen, aber nur wenn dein Script eine GUI hat oder sonst etwas spezielles GUI-Basiertes braucht, generell braucht man keine GUI!

    Das kann ich mir doch prinzipiell sparen, da wenn ich folgenden Code im Terminal eingebe:

    Code
    sudo python /home/pi/programme/Einlesen.py &

    startet mein Skript, wird ausgeführt und funktioniert auch!

    Ebenfalls funktioniert die Ausführung mit dem Check.sh:

    Code
    sudo bash /home/pi/programme/check.sh


    Zitat

    Moin,

    @Horror, danke das wir jetzt wissen das Andreas etwas überlesen hat.

    LUKI: beim Ausführen der crontab hat das System nicht die gleichen Infos (ENVIROMENT), wie wenn du dich eingeloggt hast (Stickwort: profile ) d.h. du musst die kompletten Pfade zu sudo und python angeben. Sowohl in der @-Zeile als auch im .sh.
    Ich bin mir unsicher ob es dann funktioniert, denn ein sudo in der cron.... (NUR) gefühlt keine gute Idee, aber ich kann es nicht begründen. Aber versuchs erst mal mit den Pfaden.

    Gruß Lunepi


    Das mit dem Einloggen hab ich mir schon als Fehler vorgestellt, da es einfach der einzige unterschied ist der besteht.
    Ich werde mal die Pfade raussuchen und ausprobieren. Werde mich dann melden :thumbs1:

  • Aaaah Lunepi hat absolut Recht, da liegt das Problem *die Tomaten von den Augen nehm*
    Auch der Python-Interpreter muss mit Pfad angegeben werden...
    also "/bin/python /home/pi/programme/Einlesen.py" oder wo dein python halt liegt. (Das bekommst du mit "which python" raus)
    sudo ist tatsächlich keine gute Idee, besser wäre es, das ganze in die root-crontab einzutragen (sudo crontab -e) oder noch VIEL besser: deinem Nutzer die nötige Gruppe zuzuweisen und damit kein sudo für die Situation mehr zu benötigen. Da ich nicht weiß was dein Script macht, kann ich dir nicht sagen welche das ist. Für GPIOs wäre das z.B. "dialout". Das unktioniert nicht in jedem Fall, da einige Sachen tatsächlch nur für root sind, für das meiste gibt es aber die passende Gruppe.

    Lunepi: Man kann ja mal etwas überlesen, und bei langen Threads lese ich auch nicht alles vorherige, aber DIE zwei Schlüsselinformationen, die deutlich erwähnt werden, als erster Antwortender zu übersehen und dann extra danach zu fragen... da frage ich ich schon, warum man das tut? Wenn man sich nicht die Mühe macht die Frage zu lesen, warum macht man sich dann die Mühe zu antworten? Warum gibt man Anfängern das Gefühl es nicht ordentlich beschrieben zu haben, wenn man selbst nicht lesen kann?

  • So...ich habe nun ein bisschen "ausschlussverfahren" getrieben
    Folgendes steht in meiner crontab:

    Code
    # Shell variable for cron
    SHELL=/bin/bash
    # m h  dom mon dow   command
    34 12 * * * sudo /usr/bin/python /home/pi/programme/Einlesen.py &
    0 0 * * * bash /home/pi/programme/check.sh


    Tatsächlich wurde das Skript um 12:34 Uhr ausgeführt und läuft seit dem. Das selbe habe ich auch mit meiner check.sh Datei probiert und diese vom Cron jede Minute ausführen lassen, der Start hat auch funktioniert.
    Mit dem @reboot Befehl funktioniert das ganze nicht! Also lag jetzt die Vermutung das beim Booten noch irgendwelche Module fehlen.

    also habe ich mir mit dem >> Befehl im Cron die Ausgabe umleiten lassen. Und siehe da:

    Code
    Traceback (most recent call last):
      File "/home/pi/programme/Einlesen.py", line 116, in <module>
        db = MySQLdb.connect("localhost","*******","************")
      File "/usr/lib/python2.7/dist-packages/MySQLdb/__init__.py", line 81, in Connect
        return Connection(*args, **kwargs)
      File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 187, in __init__
        super(Connection, self).__init__(*args, **kwargs2)
    _mysql_exceptions.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")


    Ich greife mit dem Skript auf eine MySQL Datenbank zu, welche wohl in dem Moment noch nicht vollständig geladen ist beim hochfahren.

    Jetzt ist meine erste Überlegung: sleep Befehl ganz oben ans Skript damit es das hochfahren abwartet.
    Oder:
    Das Skript doch über "rc.local" starten lassen und nur die check.sh über den Cron laufen lassen :denker:

    Habt ihr eventuell noch bessere Lösungsansätze? Kann die "reihenfolge" beim Hochfahren verschoben werden?

    Ich habe nun in mein Skript einen time.sleep(30) eingebaut bevor die Datenbankverbindung hergestellt werden soll. Jetzt läuft das Skript und die Log-Datei hat keinen Fehler.

    Ich denke ich belasse die Log-File....wie man sieht kann diese wohl sehr schnell helfen und einem paar Stunden suche sparen! :thumbs1:
    Vielen Dank für die Hilfe hier im Forum!

    Einmal editiert, zuletzt von Luki2508 (3. Juli 2014 um 13:17)

  • Über die rc.local hast du etwas mehr Kontrolle, wann das Script ausgeführt wird, denn das wird nach allem anderen ausgeführt.
    Noch mehr Kontrolle hast du, wenn du ein Upstart-Script erstellst: http://wiki.ubuntuusers.de/Upstart (arbeitet der Pi mit Upstart? Ansonsten mit einem init-script). Dabei kanst du genau sagen wonach und wovor das ausgeführt werden soll. Ist aber übertrieben in diesem Fall, denke ich.
    Das sleep funktioniert auch wunderbar und ist Performancetechnisch kein Problem, da sleep die CPU-Kontrolle abgibt. Aber wenn du etwas installierst was beim Hochfahren plötzlich länger dauert kann es natürlich sein, dass es plötzlich nicht mehr funktioniert... Feste Wartezeiten sind immer ein Risiko! 30s sollten da aber eigentlich genug Puffer beinhalten :)
    Etwas mehr Sicherheit hast du, wenn du am Anfang des Scriptes einfach die Verfügbarkeit der Datenbank prüfst, und wenn nicht verfügbar, dann einfach noch ein kleines sleep einwerfen und danach wieder testen... usw.

  • Habe den sleep Befehl nun auf 180 Sekunden gestellt...das sollte mehr als genug Zeit sein.

    Die Abfrage im python-Skript ob die Datenbank schon da ist währe wohl die wirklich eleganteste Lösung. Da muss ich schauen ob ich noch die Zeit für finde.

    Bei diesem Projekt handelt es sich um eine Abschlussarbeit an einer Wetterstation. Das Einlesen.py Skript liest analoge Werte aus und speichert mir diese direkt in eine MySQL Datenbank.

    Der RPi wird samt Platine mit A/D-Wandlern in einen Schaltschrank verbaut und da im Dauerbetrieb laufen.

    PS:
    Im Cronjob habe ich aktuell nur noch folgendes stehen:

    Code
    @reboot sudo python /home/pi/programme/Einlesen.py >> /home/pi/log.txt 2>&1
    */1 * * * * bash /home/pi/programme/check.sh >> /home/pi/log2.txt 2>&1

    Die Pfade zu python und bash sind also nicht nötig gewesen!

  • Jetzt kann du das ganze noch hübsch machen, was Andreas weiter oben schon vor geschlagen hat:
    Dein Python SKript mit 1. Zeile:

    #!/usr/bin/python

    und das Shellskript entsprechend:

    #!/bin/bash

    einfügen und mit "chmod o+x SKRIPT" ausführbar machen und schon kannst du dir den Aufruf des Interpreters sparen:

    sudo /home/pi/programme/Einlesen.py

    sollte reichen.

    Sieht professioneller aus.

    Ich würde persönlich rc.local oder eine eigenes rc-skript nutzen aber mit sleep gehts auch...

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

  • Würde der Pi bei mir daheim stehen, würde ich es auch wahrscheinlich so machen.

    Jedoch muss für die Hochschule und die Dokumentation alles reproduzierbar sein. Von der Installation von Debian über die Einrichtung des Apache, php, mysql, phpmyadmin,ftp bis hin zum automatischen starten der Skripte.

    Aus dem Grund möchte ich so viele Eingaben in die Konsole vermeiden, so dass ein "Nachfolger" (bzw. jemand ohne Erfahrung) der die Inbetriebnahme stupide Schritt für Schritt durchgeht auf wenig Probleme stößt. Und je mehr Eingaben getätigt werden müssen, desto eher können Fehler passieren. Ich finde schon die bearbeitung des Cronjobs und dem einfügen der Codezeilen kritisch.:rolleyes:

  • Hallo zusammen,

    hier seid ja heute puzig heute.

    Ich schreibe so als ernstgemeinte Tipp:

    Zitat


    - nicht nur das py-Skript sondern auch den Python-Interpreter starten oder
    - das py-Skript ausführbar machen

    Ihr verwerft meinen Tipp =(

    Kommt aber später zun gleichen Ergebnis? :wallbash:

    Was sagt mir das jetzt? :s


    Weiter so!

    Beste Grüsse

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Andreas: Der entscheidene Unterschied steckt im Detail. Dein Hinweis war zwar im Ansatz richtig aber nicht lösungsführend da nicht detailiert genug.
    Die Lösung war es den vollständigen Pfad zum Interpreter zu nuten, einfach nur "python" im Crontabeintrag zu nutzen hat nichts gebracht - diesen Teil hast du zudem auch überlesen: Du sagtest man solle das Script dem Interpreter übergeben aber genau das hat der TE seines Wissens nach bereits im ersten Beitrag gepostet..
    Manchmal ist es besser detailiertere Beiträge zu machen - das bringt mehr als nur mögliche Lösungen anzukratzen oder anzudeuten..


    Funktionierte nicht:

    Code
    @reboot sudo python /home/pi/programme/Einlesen.py &

    Funktioniert:

    Code
    @reboot sudo /usr/bin/python /home/pi/programme/Einlesen.py &


    Eine weitere Lösung wäre - wie auch Andreas angeschnitten hat - den Shebang im Script anzugeben und das Script ausführbar zu machen. Das wäre der elegantere Weg.

    Einer der folgenden Möglichkeiten als Erste Zeile im python Script:

    • Code
      #!/usr/bin/env python


      nutzt /usr/bin/env um den genauen Pfad zum python zu ermitteln. Achtung: Ist nicht auf allen Betriebssystemen vorhanden oder exakt /usr/bin/env

    • Python
      #!/usr/bin/python

    Script ausführbar machen:

    Code
    chmod +x /path/to/script.py


    PS: Das & am Ende des Crontabeintrags ist eigentlich quatsch


  • ... alles reproduzierbar sein
    Aus dem Grund möchte ich so viele Eingaben in die Konsole vermeiden, so dass ein "Nachfolger" (bzw. jemand ohne Erfahrung) der die Inbetriebnahme stupide Schritt für Schritt durchgeht auf wenig Probleme stößt


    Gerade Schritte auf der Konsole / Terminal, wie auch immer sind doch per Copy&Paste reproduzierbar und weniger fehleranfällig.
    Ein falscher Klick ist schnell gemacht...

    Hier mal ein (narrensicheres) Beispiel aus meiner Installations-Doku:

  • Ich denke dafür sind leider meine selbigen Kenntnisse zu eingeschränkt.:daumendreh2:

    Leider kann ich auch nicht voraussetzen das jemand mit Putty oder dem Terminal arbeitet. Es muss eben auch möglich sein, den PI an einen Monitor zu hängen, USB-Tastatur dran..und es wird losgetippt.
    Ich hoffe natürlich das sich später jemand soweit einliest das er das ganze mit Putty macht und sich die arbeit erleichtert :D. Noch besser wäre es wenn derjenige am Ende mehr Ahnung von der Geschichte hat wie ICH! Die Doku soll ja prinzipiell auch nur eine "Art" einstieg liefern, wer sich dann nicht mit weiter beschäftigt ist eh selber Schuld

  • Hallo,

    ich lese schon eine ganze Zeit lang in diesem Forum mit und bin begeistert davon, was manche Leute mit dem kleinen Raspberry Pi anstellen. Hut ab vor Eurer Arbeit hier! :bravo2:

    Das Mitlesen alleine reicht inzwischen aber nicht mehr aus und auch ich stehe jetzt prinzipiell vor selbigem Problem wie der TE. Daher schreibe ich einfach in diesen Thread und erstelle keinen neuen - hoffe, dass das okay ist.

    Verwendete Hard-/Software
    Raspberry Pi 2 - Modell B
    Kodi unter OSMC

    Würde gerne ein Python-Skript als Cronjob laufen lassen, um mir bei erhöhter CPU-Temperatur eine eMail zusenden zulassen.
    Das Skript funktioniert (manuell ausgeführt) einwandfrei. Trage ich eine Anweisung in der crontab ein (egal ob mit dem aktuellen User OSMC oder in die sudo crontab oder auch unter /etc/crontab) bekomme ich keine Mail. Habe alle in diesem Thread aufgeführten Anweisungen/Tipps beherzigt, aber gelingen will es mir leider nicht. Kann mir vielleicht jemand von Euch weiterhelfen?

    Sorry, falls ich irgendetwas nicht ganz verständlich ausgedrückt habe, bin auch (noch) kein LINUX-Experte :helpnew:

    Das von mir verwendete Skript sieht wie folgt aus:

    Spoiler anzeigen

    Und die Ausgabe bzw. Eintragung innerhalb der crontab sieht so aus:

    Code
    # m h  dom mon dow   command
    * * * * * sudo /usr/bin/python /home/osmc/cpu-temp-warning.py >/dev/null 2>&1
    #

    Habe das Skript auch ausführbar gemacht. Wäre dankbar für jeden Tipp. Verzweifle langsam, aber sicher :wallbash:

    Vielen Dank schon Vorab! :danke_ATDE:

    Beste Grüße
    Soul

  • FAQ => Nützliche Links / Linksammlung => crontab


    Zum auslesen der CPU Temperatur würde ich zudem nicht "vcgencmd" verwenden, das verursacht zu viel CPU Last. Nutze stattdessen_
    [code=php]
    def getCPUfreq():
    with open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq', 'r') as f:
    content = f.read().splitlines()
    return float(content[0]) / 1000.0

    def getPiCpuLoad():
    with open("/proc/loadavg", 'r') as f:
    content = f.readline().split(" ")[:3]
    return ' , '.join(content)

    def getPiUptime():
    with open('/proc/uptime', 'r') as f:
    uptime_seconds = float(f.readline().split()[0])
    uptime = str(timedelta(seconds = uptime_seconds))
    return uptime

    def getPiRam():
    with open('/proc/meminfo', 'r') as mem:
    tmp = 0
    for i in mem:
    sline = i.split()
    if str(sline[0]) == 'MemTotal:':
    total = int(sline[1])
    elif str(sline[0]) in ('MemFree:', 'Buffers:', 'Cached:'):
    tmp += int(sline[1])
    free = tmp
    used = int(total) - int(free)
    usedPerc = (used * 100) / total
    totalMB = int(total/1024)
    freeMB = int(free/1024)
    return "%s / %s" % (freeMB, totalMB)

    def getPiTemperature():
    with open("/sys/class/thermal/thermal_zone0/temp", 'r') as f:
    content = f.read().splitlines()
    return float(content[0]) / 1000.0
    [/php]

  • Hallo,

    vielen Dank für die schnelle Antwort!

    Habe mir die FAQ zu Crontab durchgelesen und dabei (ehrlich gesagt) meinen Fehler nicht feststellen können. Bin der Meinung, dass ich genauso wie beschrieben vorgegangen bin.

    Deinen Ratschlag nicht "vcgencmd" zu nutzen bin ich dann auch nachgegangen und habe es in meinem Skript eingebaut. Und plötzlich habe ich automatisch eMails bekommen ohne die crontab verändert zu haben ^^

    Kann ich die Temperaturausgabe mit dem von Dir genannten Befehl auch auf eine Dezimalstelle abrunden?

    Fazit: es läuft einwandfrei, auch wenn ich nicht wirklich verstanden hab, warum es jetzt klappt :rolleyes:

    Danke für die Hilfe! :thumbs1:

  • Ich vermute mal der Grund wieso es mit "vcgencmd" nicht funktionierte war der fehlende Absolute Pfad zu dem Befehl. Hat was mit Umgebungsvariablen und PATH zu tun ;)

    Du kannst natürlich alle üblichen Python Methoden anwenden und mithilfe von "round()" auch aufrunden ;)
    [code=php]
    def getPiTemperature():
    with open("/sys/class/thermal/thermal_zone0/temp", 'r') as f:
    content = f.read().splitlines()
    return round(float(content[0]) / 1000.0, 1)
    [/php]

Jetzt mitmachen!

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