Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

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;兩者應指向同一物件,並保存目錄權限與新檔擁有者。

這可區分陳舊描述元與無法存取的新路徑;CPython 問題顯示目標目錄消失時重新開啟會失敗。

3. 重新命名、建立後寫入一筆

將 app.log 改名為 app.log.1,於下一次寫入前建立權限正確的新 app.log,並保留輪替檔直到查核完成。

寫入一筆編號哨兵並 flush;新路徑 inode 必須等於描述元 inode,輪替檔仍保有舊 inode。

4. 驗證每筆編號記錄恰好一次

輪替前寫 seq-001 至 seq-003,之後寫 seq-004 至 seq-006,完整讀取兩檔;聯集須等於預期且每值只出現一次。

本機 CPython 3.12.14 測試的缺漏與重複集合皆為空,輪替後描述元與新路徑 inode 相同。

5. 拒絕掩蓋邊界的捷徑

copytruncate 不是無損等價方案;logrotate 明確警告複製與截斷之間可能遺失資料。

不要只比總行數,也不要只憑新路徑存在判定成功;缺一筆加重複一筆仍可有相同行數。

6. 記錄結論範圍

此測試只證明指定 Python、檔案系統、服務帳號和設定,不涵蓋未來輪替、遠端檔案系統、容器磁碟區或 Windows。

變更版本、處理器、策略、掛載、權限或帳號後必須重測,並監控重新開啟例外與描述元不匹配。

原創示意圖:前三筆在輪替檔,後三筆在新活動檔。
原創示意圖:編號聯集無缺漏、無重複才接受輪替。 Watch at Ease