テクノロジー · 実用ガイド
Python のログローテートで欠落?inode 切替とレコード集合を検証
ローテートの所有者を一つにし、記述子とパスを照合して、旧・新ファイルの番号付きレコードを一度ずつ確認します。

logrotate が成功し新しい app.log があっても、Python が古い inode への書き込みを止めた証明にはなりません。WatchedFileHandler は Unix 系で emit 前にデバイスと inode を確認するため、記述子・パス・レコードの三層で検証します。
ローテートの所有者は一つだけにします。外部 rename-create と WatchedFileHandler、または内部ローテート処理のどちらかを選び、境界の番号付きレコードが欠落も重複もない一つの列になることを確認します。
1. 所有者を一つだけ選ぶ
logrotate が app.log を改名して新規作成するなら WatchedFileHandler を一つだけ使い、内部ローテート処理を重ねません。
Windows や inode の意味が異なるファイルシステムでは適用を仮定せず、実際のマウントとサービス利用者で試験します。
2. 記述子とパスの同一性を記録
ローテート前に flush し、os.fstat と os.stat のデバイス番号・inode を記録します。両者は同じ対象を示す必要があります。
ディレクトリ消失時の再オープン失敗例があるため、親ディレクトリ権限と新規ファイルの所有者も保存します。
3. 改名・作成後に一件出力
app.log を app.log.1 に改名し、次の書き込み前に正しい権限で新しい app.log を作成します。
番号付きの一件を出力して flush し、新パスと記述子の inode が一致し、旧ファイルが以前の inode を保持することを確認します。
4. 各レコードが一度だけあることを証明
前に seq-001〜003、後に seq-004〜006 を書き、両ファイルを全て読みます。期待集合と一致し、各値が一度だけ必要です。
CPython 3.12.14 のローカル試験では欠落・重複は空で、ローテート後の記述子は新パス inode と一致しました。
5. 境界を隠す近道を拒否
copytruncate は無損失の同等策ではありません。公式マニュアルはコピーから切断までの損失窓を警告しています。
総行数だけを比べず、新パスの存在だけで成功としません。一件の欠落と一件の重複は同じ行数になり得ます。
6. 結果の範囲を記録
この試験は対象の Python、ファイルシステム、サービス利用者、設定だけを証明し、遠隔 FS、コンテナ、Windows までは証明しません。
版、処理系、方針、マウント、権限、利用者を変更したら再試験し、再オープン例外を監視します。
