Die Ausgabe der Druckanweisung in Python geht nicht ins Cron-Protokoll

Die Ausgabe der Druckanweisung in Python geht nicht ins Cron-Protokoll

meine Crontab sieht so aus:

@reboot sh /home/pi/LCDinterface/shutdownlauncher.sh 2>&1 | tee -a /home/cronlog

Inhalt von shutdownlauncher.sh:

cd /
cd home/pi/LCDinterface


date
python shutdown.py 
echo ''
cd /

Inhalt von shutdown.py:

if interrupt_happens:
  print ("shutting down")
  time.sleep(3)
  os.system("sudo shutdown -h now")

python shutdown.pyWenn ich oder ausführe sh shutdownlauncher.sh, kann ich in meinem Terminal immer den Ausgabetext „shutting down“ sehen. Aber wenn nur Cron das Bash-Skript ausführt, das das Python-Skript aufruft, sehe ich den Text nie und er erscheint nicht im Protokoll. Der dateBefehl im SH-Skript erscheint in meinem Protokoll, aber nicht im Terminal. Können Sie mir dabei helfen? Wie bearbeite ich den shutdownlauncher.shoder den Cron-Job, um die Ausgaben im Terminal und auch im Protokoll anzuzeigen? Das Ganze läuft auf einem Raspberry Pi 3, ich bin über SSH verbunden.

Inhalt meiner Logdatei:

Fri Apr  7 19:26:33 CEST 2017
Fri Apr  7 19:36:11 CEST 2017
Fri Apr  7 21:18:45 CEST 2017
Sat Apr  8 00:08:09 CEST 2017
Sat Apr  8 00:29:31 CEST 2017
Sat Apr  8 10:08:17 CEST 2017
Sat Apr  8 11:58:35 CEST 2017

Antwort1

Versuchen Sie, anstelle der Druckfunktion das Modul zu verwenden syslog.

import syslog
syslog.syslog('System is going to shutdown')

Antwort2

Vergleichen:

python3 -c 'import time; print("foo"); time.sleep(1); print("bar")'

Mit:

python3 -c 'import time; print("foo"); time.sleep(1); print("bar")' | cat

Sie werden feststellen, dass python3die Ausgabe von an diese Pipe geht foound barnur am Ende gedruckt wird.

Oder:

$ python3 -c 'import os, signal; print("foo"); os.kill(os.getpid(), signal.SIGTERM); print("bar")'
foo
zsh: terminated  python3 -c
$ python3 -c 'import os, signal; print("foo"); os.kill(os.getpid(), signal.SIGTERM); print("bar")' | cat
zsh: terminated  python3 -c  |
zsh: done        cat

Wie in den meisten Sprachen wird die Standardausgabe, wenn sie nicht an ein Terminalgerät (für den Benutzergebrauch) gesendet wird, gepuffert. Dadurch werden viele unnötige Schreibvorgänge vermieden.

Und da dadurch shutdownletztendlich alle Prozesse, einschließlich dieses pythonSkripts, beendet werden, wird der Puffer nie geleert.

Sie können explizit anfordern, dass der Standardausgabepuffer vor dem Aufruf geleert wird shutdown(oder killin meinem Beispiel):

$ python3 -c 'import os, signal, sys; print("foo"); sys.stdout.flush(); os.kill(os.getpid(), signal.SIGTERM); print("bar")' | cat
foo
zsh: terminated  python3 -c  |
zsh: done        cat

Aber hier sollte diese Nachricht eher an stderr als an stdout gehen und stderr wird nicht gepuffert, selbst wenn es nicht an ein TTY-Gerät geht, also:

$ python3 -c 'import os, signal, sys; print("foo", file=sys.stderr); os.kill(os.getpid(), signal.SIGTERM); print("bar")' 2>&1 | cat
foo
zsh: terminated  python3 -c  2>&1 |
zsh: done        cat

verwandte Informationen