Crontab funktioniert nicht

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Hey,

ich versuche mein Python-Script auf meinem Raspberry Pi dauerhaft auszuführen.
Habe im Internet auch zahlreiche Beispiel gefunden. Jedoch wenn ich die anwende wird nichts ausgeführt.

Ich benutze den GNU nano 2.2.6 . Ich habe folgendes Tutorial gesehen: https://www.raspberrypi.org/documentati ... ge/cron.md
Wenn ich dies so mache wird aber nichts ausgeführt. Dann habe ich ein weiteres Tutorial gesehen : https://blog.silvertech.at/python-skrip ... en-lassen/. Dort wird zusätzlich usr/bin/python angegebn. Dann habe ich es so versucht, aber es funktioniert auch nix.

Mein Crontab:
* * * * * /usr/bin/python /home/pi/programme/ofen.py

Warum ist das denn so?
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

"Funktioniert nicht" ist eine sehr allgemeingehaltene Aussage die leider nicht bei der Problemeingrenzung hilft 8)

Welchen Fehler bekommst Du denn genau? Weiterhin ist ein häufiger Fehler bei Benutzung von Scripts in der Crontab dass Programme nicht mit ihrem absoluten Pfad aufgerufen werde bzw der PATH nicht entsprechend gesetzt ist.
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Eigentlich sollte ja der Crontab das Pythonscript ofen.py dauerhaft ausführen. Dies erreicht man indem man 5 x * erstellt.
Wenn es so ist sollte doch dauerhaft die Überprüfung erfolgen, welches Signal (High oder Low) nun in den GPIO 4 eingeht.

Aber wenn ich es nun wieder teste bekomme ich trotzdessen einfach keine E-Mail und auch keine Nachricht in meiner putty console, welche ich zum Verbindungsaufbau zwischen Windows 10 und Raspberry Pi benutze.

Der Pfad ist absolut gesetzt. Ebenso ist er richtig. Habe es eben nochmal überprüft.
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

Es ist sehr ungeschickt ein Script jede Sekunde aufzurufen um ein GPIO zu prüfen. Ich würde das Script so umschreiben dass es einmal gestartet wird und dann in eine Endlosschleife mit entsprechendem Sleep von 1 Sekunde den GPIO abfragt. Oder noch besser - aber etwas komplizierter zu programmieren: Auf einen Interrupt beim GPIO warten.
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Hey,

ok alles klar.

Nur mal ne Frage. Wenn ich es jetzt so code, dass es in einer Endlosschleife ist muss ich doch das Script irgendiwe aufrufen. Aber das muss automatisch passieren. Wie bekomme ich das automatische da rein? Denn momentan muss ich es manuell machen.
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

Schreibe einfach

Code: Alles auswählen

@reboot /usr/bin/python /home/pi/programme/ofen.py
:D
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

PS: Und vergiss nicht den Sleep in der Loop. Ansonsten kannst Du irgendwann Eier auf Deiner Raspi CPU braten :lol:
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Funktioniert ebenso nicht.

Ich bekomme weder E-Mail noch eine Meldung in der Console.

Script:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf8 -*-

import RPi.GPIO as GPIO

import logging
from marrow.mailer import Message, Mailer
logging.basicConfig(level=logging.INFO)


# Benötigte Werte:
# GPIO.LOW (alles ok)
# GPIO.HIGH (fehler)

# Pin-Nummern aus dem Layout benutzen (siehe gpio.jpg)
GPIO.setmode(GPIO.BOARD); 


# input setzen auf Pin-Nummer: 7 = GPIO 4
GPIO.setup(7, GPIO.IN, pull_up_down = GPIO.PUD_DOWN);


#Überprüfung ob input einen low oder high status hat 
gpioInput = GPIO.input(7)
while gpioInput == GPIO.HIGH: 
	# Mailversand
	mail = Mailer({
        'manager.use': 'futures',
        'transport.use': 'smtp',
        'transport.host': 'smtp.gmail.com', # smtp server
        'transport.tls': 'ssl', # protokoll
        'transport.username': '', # email adresse
        'transport.password': '', # password
        'transport.max_messages_per_connection': 5
    })

	mail.start()

	message = Message([('', '')], [('Ich', '')], "", plain="")

	mail.send(message)
	mail.stop()

	print gpioInput
	print "Fertig"
	sleep(1)
else:
	print gpioInput
	print "nix"
	
Benutzeravatar
framp
User
Beiträge: 52
Registriert: Samstag 9. Oktober 2010, 22:16
Wohnort: bei Stuttgart
Kontaktdaten:

Deine Logik sitmmt nicht ganz: Du musst die GPIOs initialisieren und dann eine Endlosschleife haben, in der regelmäßig der GPIO angefragt wird und das Ergebnis davon musst Du in eine if Abfrage einbauen und dann jeweils eine Mail schreiben bzw nichts tun. Also in so etwa

Code: Alles auswählen

# initialisiere GPIO
while true:
   # read GPIO
   # if GPIO hat ungültigen Status
   #      schreibe email 
   time.sleep(1)
bogo10
User
Beiträge: 5
Registriert: Dienstag 26. Dezember 2017, 19:09

Hallo,
nur so als Denkanstoß:
Ich würde GPIO 4 nicht verwenden, ebenso andere GPIOs die eine festgelegte Funktion haben, GPIO 4 ist für 1wire vorgesehen. Gibt doch jede Menge freie GPIOs: 5, 6, 12, 13, 16- 26
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

@Moon: "Dauerhaft" klingt danach, als sollte das Skript einmal gestartet werden und dann die ganze Zeit im Hintergrund laufen. Ein Cron-Job wird allerdings in bestimmten Intervallen (mindestens eine Minute) immer wieder aufgerufen. Insofern glaube ich, dass das, ähnlich wie framp schon meinte, nicht die richtige Wahl ist. Man würde so etwas mit einer systemd Unit lösen, die du für dein Skript schreiben musst.

Ich bin mir nicht ganz sicher, welche Art von Ausgabe du erwartest. Cron führt das Skript im Hintergrund als separaten Prozess aus, da gibt es per se erst einmal keine unmittelbar sichtbare Ausgabe; das läuft völlig losgelöst von Shells du offen hast oder öffnest. Wenn dein System entsprechend konfiguriert ist, sendet der Cron-Daemon Ausgaben über die system-interne Mail-Funktion (mal per 'mail'/'mailx' nachschauen). Ansonsten könntest du den Aufruf in der Crontab so anpassen, dass stderr und stdout in eine Datei geschrieben werden. Um zu schauen, ob dein Skript überhaupt gestartet wird, kannst du ja mal in der Prozess-Liste schauen, oder ob dein Skript zwischentlich mal angezeigt wird, wenn du 'top -i' ein paar MInuten laufen lässt.
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Hey,

Vielen Dank für die Hilfe zu aller erst.

@bogo10 : Danke für die Info. Ich werde mir dies mal anschauen und mich doch umentscheiden.

Nun zum Problem:
Da ich nun erkannt habe, dass es doch schwachsinnig ist jede Sekunde das Script auszuführen um dies zu erkennen habe ich mich doch entschlossen einen Interrupt zu erstellen. Habe mir dazu auch schon mehrere Seiten angeschaut und durchgearbeitet. Jedoch wird nichts ausgeführt.

Mir kommt es so vor als springt es nicht mal in die while schleife rein.

Mein Script:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf8 -*-

import RPi.GPIO as GPIO
import time
import logging
from marrow.mailer import Message, Mailer
logging.basicConfig(level=logging.INFO)


# Benötigte Werte:
# GPIO.LOW (alles ok)
# GPIO.HIGH (fehler)

# Pin-Nummern aus dem Layout benutzen (siehe gpio.jpg)
GPIO.setmode(GPIO.BOARD); 


# input setzen auf Pin-Nummer: 7 = GPIO 4
GPIO.setup(7, GPIO.IN, pull_up_down = GPIO.PUD_DOWN);





# Callbackfunction definieren
def sendEmail():

			# GPIO input setzen
			gpioInput = GPIO.input(7);

			# Interrupt-Event mit Callbackfunction setzen
                  # GPIO, Erkennung einer steigenden Flanke, Callbackfunction
			GPIO.add_event_detect(gpioInput, GPIO.RISING, callback=sendEmail)

			while True:


				if gpioInput == GPIO.HIGH :
					# Mailversand
					mail = Mailer({
				        'manager.use': 'futures',
				        'transport.use': 'smtp',
				        'transport.host': 'smtp.gmail.com', # smtp server deines emailanbieters
				        'transport.tls': 'ssl', # protokoll
				        'transport.username': '', # deine email adresse
				        'transport.password': '', # dein password
				        'transport.max_messages_per_connection': 5
				    })

					mail.start()

					message = Message([('test', '')], [('Ich', '')], "Warnung!", plain="test")
					#message = Message([('Heizungsfehlerinformation ( = Titel der E-Mail)', 'emailadresseDesAbsenders')], [('Ich', 'emailadresseAnderDieE-MailgesendetWird')], "Warnung! (= Betreff der E-Mail)", plain="Die Heizung im EG gibt ein Highsignal zurück. Das heißt irgendwas stimmt nicht! ( = E-Mail Text)")

					mail.send(message)
					mail.stop()

					print gpioInput
					print "Fertig"
					time.sleep(1)
				else:
					print gpioInput
					print "Alles gut"
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist kompletter Murks. Wenn du Schwierigkeiten mit den Konzepten interrupt-basierter Programmierung hast, dann benutz doch einfach wait_for_edge und gut ist.
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Warum ist denn das kompletter Murks?

Ich habe dies von dieser Seite: http://www.netzmafia.de/skripten/hardwa ... O_int.html
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@Moon: außer dass der Code, der auf der von Dir verlinkten Seite, wie bei fast allen RaspPi-Seiten leider der Fall, nicht wirklich toll ist, sehe ich nicht, was das mit dem zu tun hat, was Du hier zeigst.

Interrupts haben spezielle Probleme, so dass man normalerweise nicht freiwillig welche benutzt. Für Dich ist »wait_for_edge« viel besser geeignet.
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Hey,

ok alles klar.

Ich habe jetzt hier geschaut wie man wait_for_edge einsetzt.
Ich verstehe nicht woher channel kommt. Ist der Channel nun GPIO.input(pinNummer) oder nur die Pinnummer?

Bei diesem Code kommt nun folgene Fehlermeldung:
Traceback (most recent call last):
File "programme/ofen.py", line 23, in <module>
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout = None)
NameError: name 'GPIO_RISING' is not defined

Wie kann es sein?

Code:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf8 -*-

import RPi.GPIO as GPIO
import time
import logging
from marrow.mailer import Message, Mailer
logging.basicConfig(level=logging.INFO)


# Benötigte Werte:
# GPIO.LOW (alles ok)
# GPIO.HIGH (fehler)

# Pin-Nummern aus dem Layout benutzen (siehe gpio.jpg)
GPIO.setmode(GPIO.BOARD) 


# input setzen auf Pin-Nummer: 7 = GPIO 4
GPIO.setup(7, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

channel = 7
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout = None)	

#while True:

if channel is None :
	print "Alles gut"
else:
		# Mailversand
	mail = Mailer({
		'manager.use': 'futures',
		'transport.use': 'smtp',
		'transport.host': 'smtp.gmail.com', # smtp server deines emailanbieters
		'transport.tls': 'ssl', # protokoll
		'transport.username': '', # deine email adresse
		'transport.password': '', # dein password
		'transport.max_messages_per_connection': 5
	})

	mail.start()

	#message = Message([('test', '')], [('Ich', '')], "Warnung!", plain="test")
	message = Message([('Heizungsfehlerinformation ( = Titel der E-Mail)', '')], [('Ich', '')], "Warnung! (= Betreff der E-Mail)", plain="Die Heizung im EG gibt ein Highsignal zurück. Das heißt irgendwas stimmt nicht! ( = E-Mail Text)")

	mail.send(message)
	mail.stop()

	print "Fertig"
	time.sleep(1)
		
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

@Moon: weil Du GPIO_RISING nicht definiert hast, das ist nur im Modul GPIO.
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

Wie soll ich es denn definieren? Verstehe nicht.

Das Modul GPIO habe ich bereits auf meinem Pi installiert.
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Schau dir mal gaaaaaaanz genau an was du geschrieben hast, und wie die anderen Dinge mit GPIO aussehen....
Moon
User
Beiträge: 37
Registriert: Mittwoch 20. Dezember 2017, 15:21

GPIO und die Optionen (Rising, Both, ..) wurden mit nem . verbunden? Meinst du das?

Wenn ich es so mache dann kommt folgende Fehlermeldung:
Traceback (most recent call last):
File "programme/ofen.py", line 23, in <module>
channel = GPIO.wait_for_edge(channel, GPIO.RISING, timeout = None)
TypeError: an integer is required
Antworten