簡體   English   中英

讀取旋轉日志文件和文件鎖定

[英]Reading rotation log files and file locking

我有一個Python服務將日志吐出到文本文件。 它每隔約400KB旋轉一次。 所以Python服務打開了文件的句柄,我們稱之為app.log 然后,它會立即將內容寫入文件,並再次將其刷新到磁盤。 當它達到一定大小時,它會關閉它的句柄,並將其移動到app.log.1並在app.log上啟動一個新句柄。

所以我無法更改此服務,但我有一個C#應用程序將讀取這些日志。 我遇到了3個場景:

  • 如果我只是嘗試使用new FileStream(path, FileMode.Open);讀取那些日志new FileStream(path, FileMode.Open); ,它不允許我,因為Python服務有一個句柄。
  • 如果我嘗試使用new FileStream(path, FileMode.Open, FileAccess.Read);打開它new FileStream(path, FileMode.Open, FileAccess.Read); ,這允許我閱讀它,但如果服務試圖旋轉日志,它將無法,因為我的C#應用​​程序現在有文件的句柄。
  • 如果我嘗試使用new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Delete);打開文件new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Delete); ,我的Python服務在刪除文件時不會失敗,但是在app.log上創建一個新句柄會失敗,因為C#應用程序仍然會有一個句柄。

我所知道的唯一解決方案是使用Windows Shadow Copy(VSS)來創建日志快照,然后讀取該快照,但這將非常昂貴,因為我們需要每5分鍾查詢一次日志。

另外,我對閱讀旋轉日志, app.log.1app.log.2等不感興趣。

在Windows下記錄文本文件似乎是所有鎖定/句柄的痛苦。 有沒有人有任何建議?

您應該能夠像Dmitry Popov在下面的回答中所建議的那樣打開您的文件並且不會影響Python寫入它,但是它取決於Python應用程序對文件的鎖定,它可以完全鎖定您並且沒有任何關系沒有黑客入侵Windows就可以做到這一點。

FileSream fs = File.Open(@"c:\Test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)

在對其執行操作系統文件移動操作以重命名后,以這種方式創建的FileStream對象仍將連接到同一文件。

因此,假設您的python應用程序打開一個名為Test.log的文件並開始寫入它。 您可以使用從上面的行返回的文件流讀取寫入它的任何數據(在python刷新其緩沖區之后)。 python應用程序可以按照每次寫入的頻率關閉並重新打開文件,並且讀取應用程序將保持與其連接。 當python應用程序發出文件移動操作以將文件重命名為Test1.log時,上面返回的文件流仍將連接到現在稱為Test1.log的文件,因此您可以在開始之前繼續讀取文件的末尾新日志文件,如果這是你想要的。 有一點需要注意。 Python應用程序需要使用移動/重命名操作,而不是將文件復制到新文件並刪除舊文件,但如果這是它的功能,我會感到驚訝。

在您的書寫應用程序完成閱讀之前,您的閱讀應用程序可能會到達文件的末尾。 在這種情況下,fs.Read將在超時后繼續返回0,直到寫入應用程序打開文件並寫入更多內容。 如果需要,您可以將時間設置為非常長/無限。

由於您不想在啟動新文件之前讀取到一個文件的末尾,因此您可以關閉並定期重新打開文件。 沒有數字后綴的日志文件應始終是最新的。

但是,如果您希望讀取應用程序在下一個日志文件開始之前讀取到一個日志文件的末尾,則需要在寫入應用程序寫入日志文件時解決。 此外,它需要找出現在調用的文件,以便下次讀取n-1。 是否有一些由python應用程序編寫的標記,你可以尋找它來表示文件的結尾? 它寫的是“日志結束”還是類似的東西?

還要注意,當LogFile n-1不存在時,會有很短的時間。 這是因為如果你有日志文件0,1,2和3,它需要將日志文件3放入日志文件4,然后才能將日志文件2放入日志文件3.雖然這樣做會有一段短暫的時間有日志文件0,1,2,4和3的時間。

就個人而言,我會發現為Python應用程序編寫日志記錄的開發人員首先給他/她造成這種頭痛的邪惡之眼。 使最新的日志文件具有最大數量有什么問題?

using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
  //Do works
}

在這種情況下,C#thread不會鎖定文件,您的Python腳本可以寫入並關閉該文件以創建另一個沒有死鎖的文件。

您可以組合FileShare標志:

FileShare.Write | FileShare.Delete

這是一個演示:

using (var cSharp = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Write | FileShare.Delete))
{
    // The Python service will be able to change and to rename the file:
    using (var python = new FileStream(filename, FileMode.Open, FileAccess.Write, FileShare.Read))
    {
    }
    File.Move(filename, newFilename);
}

您將不得不處理並發問題。 您可以使用FileSystemWatcher來監視文件更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM