2010-07-22 28 views
1

這是處理: 我有一個多進程系統(pre-fork模型,類似於apache)。所有進程都寫入相同的日誌文件(實際上是一個記錄請求和響應的二進制日誌文件,但不管)。旋轉日誌無需重新啓動,多個進程問題

我防止經由共享內存鎖定併發訪問日誌,並且當文件達到一定的大小注意到它首先通過滾動日誌的過程:

  1. 關閉文件。
  2. 重命名log.bin - > log.bin.1,log.bin.1 - > log.bin.2等等。
  3. 刪除日誌超出允許的最大日誌數。 (比如說,log.bin.10)
  4. 打開一個新的log.bin文件

的問題是,其他過程都不知情,並且在事實上繼續寫入舊的日誌文件(後來改名到log.bin.1)。

我能想到的幾個解決方案:

  1. 某種RPC的通知其它進程重新打開日誌(甚至可能是葛)。我不特別喜歡它。
  2. 進程通過打開的文件流檢查文件長度,並以某種方式檢測到文件已在其下重命名並重新打開log.bin文件。

這些在我看來都不是很優雅。

想法?建議?

回答

3

您的解決方案看起來不錯,但是您應該將當前日誌記錄文件inode的整數存儲在共享內存中(請參閱stat(2)stat.st_ino成員)。

通過這種方式,所有進程都使用打開的inode文件保留了局部變量。

當只有一個進程旋轉時,必須更新共享變量,並且通過檢查本地inode和共享inode之間的差異來知道所有其他進程。它應該導致重新開放。

+0

我試圖根據打開文件(ftell/tellg)和磁盤上當前日誌文件的大小之間的長度差異來執行旋轉檢測。 這不是100%的防彈,但應該在這種情況下工作,不需要任何共享內存。 – 2010-07-22 09:32:39

+0

你已經使用共享互斥共享內存,它只是一個整數,除了有一個100%的防彈:-)恕我直言,測試大小差異將隨機工作,並將頭痛的傾向。 – Doomsday 2010-07-22 09:43:11

+0

是的,但它是一個簡單的boost :: interprocess :: file_lock。任何方式,我認爲這是最好的答案,因爲它是最有效的記錄和旋轉的結果。 – 2010-07-22 11:05:47

1
  1. 如何在寫入日誌條目之前每次按名稱打開文件?

    1. 得到共享內存鎖的名字
    2. 寫日誌條目
    3. 關閉文件
    4. 釋放鎖
  2. 或者你可以創建一個記錄過程,它接收

  3. 打開文件記錄來自其他進程的消息,並處理所有從它們透明地旋轉的消息。

+0

寫入記錄後關閉文件是一個不錯的主意 - 除非會增加日誌開銷。在我的情況下它可能是合適的,因爲我最多隻能得到2-3次記錄事件/秒。 新的記錄器過程將增加系統複雜性並傷害健壯性。我在尋找一個簡單的解決方案。 – 2010-07-22 09:15:01

1

你不說你正在使用什麼語言,但你的進程應該都登錄到一個日誌進程,並且日誌進程會提取文件寫入。

Logging client1 -> | 
Logging client2 -> | 
Logging client3 -> | Logging queue (with process lock) -> logging writer -> file roller 
Logging client4 -> | 
+0

這個問題有一個C++標籤。 – foraidt 2010-07-22 09:05:41

+0

問題在於,如果日誌進程死亡,則不會從任何其他進程獲得日誌。 – 2010-07-22 09:16:58

1

你可以副本 log.bin到log.bin.1和然後截斷的log.bin文件。 所以這些問題仍然可以寫入舊的文件指針,它現在是空的。

man logrotate參見:

copytruncate 
      Truncate the original log file to zero size in place after cre‐ 
      ating a copy, instead of moving the old log file and optionally 
      creating a new one. It can be used when some program cannot be 
      told to close its logfile and thus might continue writing 
      (appending) to the previous log file forever. Note that there 
      is a very small time slice between copying the file and truncat‐ 
      ing it, so some logging data might be lost. When this option is 
      used, the create option will have no effect, as the old log file 
      stays in place. 
+0

這是我考慮的一個選項,但由於bin日誌文件當前設置爲以100mb旋轉,因此這將是一個非常昂貴的循環。我正在尋找一個輕量級的解決方案。 – 2010-07-22 09:13:07

1

由於您使用的共享內存,如果你知道很多過程是如何使用日誌文件。 您可以在共享內存中創建一個標記數組,告訴每個進程該文件已被旋轉。每個進程然後重置標誌,以便它不會連續重新打開文件。