【要約】Python のログが 0 バイトのまま消えた話 — systemd timer × SIGTERM の落とし穴 [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者がRaspberry Pi上でPythonジョブを運用中、ログが0バイトになる問題に直面した。systemd timerの制限時間(RuntimeMaxSec)によりプロセスがSIGTERMで終了した際に発生する。
- ・Pythonのstdoutがファイル出力時にフルバッファリング(4KB)となる。
- ・SIGTERM受信時、Pythonはatexitハンドラを実行せずに即座に終了する。
- ・bashのリダイレクトは、子プロセスのメモリ内バッファをフラッシュできない。
// Approach
開発者はログ消失を防ぐため、バッファリング制御と出力先の変更、シグナルハンドリングの3つの観点から対策を検討した。
- ・
PYTHONUNBUFFERED=1を設定し、writeごとに即時フラッシュさせる。 - ・
StandardOutput=journalを採用し、systemdのjournaldへ直接ログを転送する。 - ・
signalモジュールを用いてSIGTERMを捕捉し、明示的にlogging.shutdown()を呼ぶ。 - ・
KillSignal=SIGINTへ変更し、PythonのKeyboardInterruptで捕捉しやすくする。
// Result
開発者は、運用負荷と信頼性のバランスを考慮し、journaldへの出力とバッファ無効化を組み合わせた構成を採用した。
- ・ログ消失のリスクを完全に排除した。
- ・ログローテーションの管理コストを削減した。
- ・
journalctlによる一元的なログ管理を実現した。 - ・SDカードの寿命を考慮したログ管理が容易になった。
Senior Engineer Insight
> 本件は「正常系では動くが異常系で証拠が消える」という、運用上極めて厄介な問題である。小規模なスクリプトほどバッファに溜まるデータが少なく、この罠に陥りやすい。対策として
journaldへの集約を推奨する。これはログローテーションやストレージ管理の観点からも、モダンなLinux運用におけるベストプラクティスと言える。