【Python】nohup.outにログが出力されない時の解決法

pythonでnohup.putのログが出力されないときの解決法 Python

発生した事柄

nohupはハングアップシグナルを無視してコマンドを実行するため、SSH接続が切断したり、ターミナルが終了、ログアウトした場合でも、実行中のコマンドを終了させずにバックグランド実行ができます。
nohupコマンドを実行すると、デフォルトではnohup.outにログが出力されます。

今回は、Pythonスクリプトでのnohup使用時に発生した“リアルタイムにログが出力
されない”という事柄についての原因と解決法を紹介します。

問題が発生したソースコード

以下のような5秒ごとに現在日時を出力する処理を5回繰り替えすコードがあるとします。

import time
import datetime

for i in range(0, 5):
    dt_now = datetime.datetime.now()
    print(dt_now)
    time.sleep(5)

これをバックグラウンドで実行します。

$ nohup python3 sample02.py &

実行するとnohup.putが自動的に生成されますが、リアルタイムでは何も出力されず、すべての処理が終了してからまとめて5回分の日時が出力されます。

原因

Pythonの場合、標準出力のバッファリングを明示的にオフにしないとプログラムが終了するまで標準出力されないことが原因でした。

バッファリングとは、ファイルを読み書きする際などに一時的にデータを記憶しておくことを意味します。

解決法

原因も分かったところで、以下のポイントを踏まえてソースコードを修正していきます。

標準出力に明示的にフラッシュするように指定する
指定する方法はsys.stdout.flush() またはprint()に flush=Trueを引数で渡す

import time
import datetime
import sys

for i in range(0, 5):
    dt_now = datetime.datetime.now()
    sys.stdout.flush() # flushさせる
    print(dt_now)
    # または print(dt_now , flush=True)
    time.sleep(5)

修正したコードでもう一度バックグラウンド実行させると実行中にリアルタイムでnohup.outに出力されていました。

pythonコマンドオプションでの解決法

$ nohup python3 -u sample02.py &

pythonコマンドのオプション-uをつけるとバッファリングが無効になり、ソースコードを修正しなくてもリアルタイムでの標準出力がされるようになります。
参照:https://docs.python.org/ja/3/using/cmdline.html#cmdoption-u

まとめ

nohupコマンドを使ったときに発生した“リアルタイムでログが出力されない”という現象にはバッファリングが関係していることが分かりました。
リモートサーバ上で時間のかかるタスクを実行し、ログは随時確認しておきたい場合などに覚えておくと役立つと思います!

タイトルとURLをコピーしました