テクノロジー · 実用ガイド

Python のログローテートで欠落?inode 切替とレコード集合を検証

ローテートの所有者を一つにし、記述子とパスを照合して、旧・新ファイルの番号付きレコードを一度ずつ確認します。

rename-create 前後のログパスと開いた記述子のデバイス番号・inode を比較するオリジナルイラスト。
オリジナルイラスト:最初のローテート後レコードで記述子が新パス inode に切り替わることを確認します。 Watch at Ease

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 までは証明しません。

版、処理系、方針、マウント、権限、利用者を変更したら再試験し、再オープン例外を監視します。

旧ファイルに前三件、新ファイルに後三件を示すオリジナルイラスト。
オリジナルイラスト:番号付き集合に欠落も重複もない場合だけ合格です。 Watch at Ease