Вывод оператора печати в Python не попадает в журнал cron

Вывод оператора печати в Python не попадает в журнал cron

Мой crontab выглядит так:

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

Содержание shutdownlauncher.sh:

cd /
cd home/pi/LCDinterface


date
python shutdown.py 
echo ''
cd /

Содержание shutdown.py:

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

Если я запускаю python shutdown.pyили sh shutdownlauncher.shя всегда могу увидеть текст вывода 'shutting down' в моем терминале. Но если только cron запускает запуск скрипта bash, который вызывает скрипт python. Я никогда не вижу текста, и он не отображается в журнале. Команда dateв скрипте sh отображается в моем журнале, но не в терминале. Можете ли вы мне помочь с этим? Как отредактировать shutdownlauncher.shили задание cron, чтобы увидеть выходные данные в терминале, а также в журнале? Все это работает на Raspberry Pi 3, я подключен по SSH.

Содержимое моего лог-файла:

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

решение1

Вместо функции печати попробуйте использовать модуль syslog.

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

решение2

Сравнивать:

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

С:

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

Вы заметите, что когда python3выходные данные поступают в этот канал, fooони barвыводятся только в конце.

Или:

$ 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

Как и в большинстве языков, когда стандартный вывод не отправляется на терминальное устройство (для потребления пользователем), он буферизуется, что избавляет от необходимости выполнять слишком много ненужных операций записи.

А поскольку в результате shutdownвсе процессы, включая этот скрипт, завершаются python, буфер никогда не очищается.

Вы можете явно запросить очистку буфера stdout перед вызовом shutdown(или, как killв моем примере):

$ 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

Но здесь это сообщение должно быть направлено в stderr, а не в stdout, а stderr не буферизуется, даже если не направляется на устройство tty, поэтому:

$ 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

Связанный контент