ファイルロガーを使用すると、stderrはstdoutの前にフラッシュされます。

ファイルロガーを使用すると、stderrはstdoutの前にフラッシュされます。

私のPythonコード:

import sys
print "i am a daemon"
print "i will be run using nohup"
sys.stderr.write("i am an error message inside nohup process\n")

コードを実行すると、python a.py次のように表示されます。

i am a daemon
i will be run using nohup
i am an error message inside nohup process

コードを実行すると、nohup python a.py > a.log 2>&1 < /dev/null &a.logが表示されます。

i am an error message inside nohup process
i am a daemon
i will be run using nohup

stdoutログを使用するとstderrログがフラッシュ/記録されるのはなぜですかnohup

答え1

私はそれが重要ではないと思いますnohup。これにより同じ動作が発生しますpython a.py > a.log 2>&1

Pythonは内部的にCファイルstdioを使用する可能性が高いです。これにより、stdout端末にいるときにラインバッファリングが発生し、stdoutファイルのときにバッファリングが発生します。stderr常にバッファリングされません。

stdoutファイルにリダイレクトすると、stdoutバッファリングがラインバッファリングからバッファリングに切り替わり、printed文字列がバッファに入り、プログラム(ストリーム)が閉じられたときにのみフラッシュされます。ストリームはstderrバッファリングされないため、ファイルに高速に転送されます。

stdbufadjustStandardBufferingを使用して、行を正しい順序で強制的に印刷できます。

stdbuf -o0 python a.py  >a.log 2>&1

答え2

これはほとんどの言語で出力ストリームの一般的な動作です。バッファリングつまり、writeメモリ内のバッファが実際に書き込まれ、バッファが一括してストリームに書き込まれます。端末に書き込むときに標準出力はラインバッファリングされますが(つまり、改行文字が印刷されるたびに実際の書き込みが発生します)、通常のファイルまたはパイプに書き込むときに標準出力は完全にバッファリングされます(データはメモリに書き込まれるまで)バッファがいっぱいです。)Stderrはバッファリングされていないか、ラインバッファリングされています。

Pythonでは、ファイルを開くときにバッファリングの種類を選択できますが、標準ストリームは選択できません。すべてのストリームをバッファリング解除するには、以下を設定できます。PYTHONUNBUFFERED環境変数は、標準ストリームがバッファリングされないように強制します。またはできますstdbufまたは、以下からプログラムを実行してください。unbuffer

ただし、標準出力がリダイレクトされたときにプログラムが正しい順序で出力をエクスポートしない場合、これは修正する必要があるプログラムの欠陥です。特に、stdoutに書き込まれた出力に関連するエラーメッセージを発行するには、まずstdoutをフラッシュする必要があります。

print some_data
if errro_condition():
    file.stdout.flush()
    sys.stderr.write('Bad stuff happened\n')

関連情報