2011-10-20 126 views
1

我有一個守護程序,它可以在整個操作過程中打開一個文件並將其寫入(通常每次都是幾天)。爲了支持日誌旋轉,我希望能夠識別句柄引用的文件位於原始位置的新位置。從Linux中的文件句柄確定文件路徑

這可能嗎? fstat()不會爲這種情況提供任何有用的信息。

我目前的解決方案是在日誌寫入功能中測試日誌文件的存在,如果它不存在,關閉舊的句柄並打開一個新的句柄。這工作,但是是黑客,並有一定的侷限性。在我的情況下,我們的系統組使用一個工具進行日誌輪換,要求他們在旋出後觸摸文件,這導致我的守護進程繼續認爲它的文件句柄指向正確的位置。

+0

看看這個線程,看看在PHP手冊中是否有類似的功能。 http://stackoverflow.com/questions/1188757/getting-filename-from-file-descriptor-in-c – Jake

回答

3

這是一個想法。它不是便攜式的,我不完全確定它是否工作或是可靠的,這讓我感到有點不安,但你可以在/proc/%d/fd/%d上使用readlink,其中第一個%dgetpid()的結果,第二個是你的文件描述。

雖然這裏有一些注意事項。首先,面對同時發生的重新命名,整個「走這條路+做某件事」的方法將具有競爭條件。另外,您的日誌文件可能有其他鏈接。我不知道在面對重命名時,/proc中的鏈接的行爲是什麼。

+0

proc文件獲取文件描述符;它不會給你一個'fstat'的不同答案# – mkj

+0

@mkj你確定嗎?最後我知道'struct stat'沒有名稱字段。 – asveikau

+0

這不是一個名稱字段,它是一個'st_ino'字段,它爲您提供inode編號。 – mkj

0

您可以簡單地定期重新獲取您的文件句柄(模式爲a),例如每24小時一次。這允許你繼續日誌記錄,儘管存在虛弱和錯誤(因爲重命名文件和重新觸摸它之間存在不可避免的競態條件)日誌輪轉實用程序。

0

fstat爲您提供了一個inode號碼,它將在日誌旋轉時更改。

http://php.net/manual/en/function.fstat.phphttp://www.php.net/manual/en/function.lstat.php

您可以從fstatlstat inode編號比較節點號碼;如果它們不同,請重新打開。

處理這個在過去的Unix守護進程的標準方法已經趕上SIGHUP並把它作爲一個信號,重新打開日誌文件,並有日誌旋轉腳本發送SIGHUP

+0

從我的測試中,移動文件時,inode不會改變。由於似乎沒有一個好的,可靠的解決方案,我認爲處理SIGHUP可能是我最終走向的方式。 – Mark

+0

的確,inode號碼在文件移動時不會改變。如果文件描述符中的「fstat」在打開文件時在文件名稱上產生了與「lstat」不同的inode編號,則該文件在您打開文件後已被移動或刪除。所有這一切說,實施'SIGHUP'處理是Unix方式。檢查'lstat'與'fstat'是備份策略,以防有人忘記發送'SIGHUP'。 – mkj