logrotate 日誌切割 原理

logrotate 原理

logrotate 是怎麼做到滾動日誌時不影響程序正常的日誌輸出呢?logrotate 提供了兩種解決方案。

  1. create
  2. copytruncate

Linux 文件操作機制

介紹一下相關的 Linux 下的文件操作機制。

Linux 文件系統裏文件和文件名的關係如下圖。

 

目錄也是文件,文件裏存着文件名和對應的 inode 編號。通過這個 inode 編號可以查到文件的元數據和文件內容。文件的元數據有引用計數、操作權限、擁有者 ID、創建時間、最後修改時間等等。文件件名並不在元數據裏而是在目錄文件中。因此文件改名、移動,都不會修改文件,而是修改目錄文件。

借《UNIX 環境高級編程》裏的圖說一下進程打開文件的機制。

 

進程每新打開一個文件,系統會分配一個新的文件描述符給這個文件。文件描述符對應着一個文件表。表裏面存着文件的狀態信息(O_APPEND/O_CREAT/O_DIRECT…)、當前文件位置和文件的 inode 信息。系統會爲每個進程創建獨立的文件描述符和文件表,不同進程是不會共用同一個文件表。正因爲如此,不同進程可以同時用不同的狀態操作同一個文件的不同位置。文件表中存的是 inode 信息而不是文件路徑,所以文件路徑發生改變不會影響文件操作。

create

這也就是默認的方案,可以通過 create 命令配置文件的權限和屬組設置;這個方案的思路是重命名原日誌文件,創建新的日誌文件。詳細步驟如下:

  1. 重命名正在輸出日誌文件,因爲重命名只修改目錄以及文件的名稱,而進程操作文件使用的是 inode,所以並不影響原程序繼續輸出日誌。
  2. 創建新的日誌文件,文件名和原日誌文件一樣,注意,此時只是文件名稱一樣,而 inode 編號不同,原程序輸出的日誌還是往原日誌文件輸出。
  3. 最後通過某些方式通知程序,重新打開日誌文件;由於重新打開日誌文件會用到文件路徑而非 inode 編號,所以打開的是新的日誌文件。

如上也就是 logrotate 的默認操作方式,也就是 mv+create 執行完之後,通知應用重新在新文件寫入即可。mv+create 成本都比較低,幾乎是原子操作,如果應用支持重新打開日誌文件,如 syslog, nginx, mysql 等,那麼這是最好的方式。

不過,有些程序並不支持這種方式,壓根沒有提供重新打開日誌的接口;而如果重啓應用程序,必然會降低可用性,爲此引入瞭如下方式。

copytruncate

該方案是把正在輸出的日誌拷 (copy) 一份出來,再清空 (trucate) 原來的日誌;詳細步驟如下:

  1. 將當前正在輸出的日誌文件複製爲目標文件,此時程序仍然將日誌輸出到原來文件中,此時,原文件名也沒有變。
  2. 清空日誌文件,原程序仍然還是輸出到預案日誌文件中,因爲清空文件只把文件的內容刪除了,而 inode 並沒改變,後續日誌的輸出仍然寫入該文件中。

如上所述,對於 copytruncate 也就是先複製一份文件,然後清空原有文件。

通常來說,清空操作比較快,但是如果日誌文件太大,那麼複製就會比較耗時,從而可能導致部分日誌丟失。不過這種方式不需要應用程序的支持即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章