Pythonの出力print文がcronログに記録されない

Pythonの出力print文が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常にターミナルに「シャットダウン」という出力テキストが表示されます。ただし、cron のみが bash スクリプトの実行を開始し、それが python スクリプトを呼び出します。テキストは表示されず、ログにも表示されません。shdateスクリプトのコマンドはログに表示されますが、ターミナルには表示されません。これについて手伝っていただけますか?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

print 関数の代わりに、モジュールを使用してみてください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

しかし、ここでは、そのメッセージは stdout ではなく stderr に送信される必要があり、tty デバイスに送信されない場合でも stderr はバッファリングされないため、次のようになります。

$ 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

関連情報