進程打開了不在任何檔案系統上的索引節點?

進程打開了不在任何檔案系統上的索引節點?

所以我試圖找出stderr一個進程是否已被重定向到一些不尋常的地方(它是一個java進程,我想要一個線程轉儲,但它是透過一堆啟動腳本啟動的)。

我用 找到我的流程pgrep,並用它pfiles來查看那裡有什麼:

4366:/foo/bar/platform/solaris2/jre_1.5.0/bin/java -Xmx2048m -Xms10
目前 rlimit:65536 個檔案描述符
 0:S_IFCHR模式:0666 dev:302,0 ino:6815752 uid:0 gid:3 rdev:13,2
    O_RDONLY|O_LARGEFILE
    /devices/pseudo/mm@0:null
 1:S_IFREG模式:0640 dev:85,56 ino:26471 uid:0 gid:0大小:10485812
    O_WRONLY|O_LARGEFILE
 2:S_IFREG模式:0640 dev:85,56 ino:26471 uid:0 gid:0大小:10485812
    O_WRONLY|O_LARGEFILE
 3:S_IFCHR模式:0666 dev:302,0 ino:6815772 uid:0 gid:3 rdev:13,12

所以我可以看到stdoutstderr(文件描述符 1 和 2)指向同一個地方;我認為它們被重定向到啟動腳本中的同一個文件,所以這相符。

但是當我查找 inode 編號為 26471 的檔案時,我看到了以下內容:

# 查找/-inum 26471
/usr/share/man/man3mlib/mlib_MatrixScale_S16_U8_Sat.3mlib
/proc/4366/fd/1
/proc/4366/fd/2
/proc/4366/fd/83

第一個命中是(我確定)不同檔案系統上的檔案。中的三個條目/proc是我的進程已開啟的 fd。

看看/proc/4366,我看不到比我得到的更多資訊pfiles

# ls -li 0 1 2 3
   6815752 c--------- 1 根系統 13, 2019 年 1 月 2 日 14:10 0
     26471 --w-------- 0 根 根 10485812 一月 20 日 13:42 1
     26471 --w-------- 0 根 根 10485812 一月 20 13:42 2
   6815772 c--------- 1 根系統 13, 12 六月 7 2009 3
# 文件 0 1 2 3
0:字元特殊(13/2)
1:ascii文本
2:ascii文本
3:人物特殊(13/12)

(我可以追蹤這些檔案描述符之一並找出它是哪個檔案。我這麼問是因為我顯然沒有足夠深入地理解檔案描述符和 inode 之間的關係)。

所以我的過程是寫給某物(在某些裝置上,索引節點為 26471),然後資料將進入具有不同索引節點號的檔案中。誰能告訴我這可能是什麼(或甚至讓我知道我到目前為止的推理是否完全被打破)?

答案1

AFAIK,find搜尋檔案系統的目錄。如果該檔案已被刪除但由於它是開啟的而仍然存在(unix 上的常見技巧),則find.

我沒有在 Solaris 中嘗試過,但是這裡是關於使用lsof識別此類“已刪除但打開”文件並通過cat /proc/<procid>/fd/<fdid> > /tmp/xxxx

編輯:

看來您已經發現了這種情況,但仍然想知道這怎麼可能。這是一個簡短的解釋:

在 POSIX 檔案系統上,檔案由其處理inode,目錄只不過是「path => inode」映射。您可以有多個路徑「指向」同一個 inode(稱為硬連結),並且 inode 會記錄它擁有的連結數量。該rm命令只是呼叫unlink()此路徑,這會減少連結計數並「可能」刪除檔案本身。

但是目錄樹上的路徑並不是 inode 的唯一可能引用,fd正在運行的進程上的開啟也很重要,而且「已刪除」檔案只有在變成 0 時才會真正刪除。

正如我在上面提到的,這是一個常見的技巧:如果您有一個在進程完成運行後不想保留的臨時文件,只需打開它並立即「刪除」它。打開的句柄將可靠地工作,當您的進程完成(正常、終止或崩潰)時,系統將刪除該句柄並徹底刪除臨時檔案。

日誌檔案不太可能是這種「隱藏自動刪除」檔案的候選者。但不小心做到這一點並不難。

由於您刪除的日誌檔案仍然有效並正在收集數據,因此簡單地複製內容似乎沒有多大幫助。因此,嘗試創建一個到 /proc//fd/ 文件的新硬鏈接,例如ln /proc/4366/fd/1 /tmp/xxxx.請注意,沒有-s標誌,因此ln應該創建一個與原始索引節點相同的新硬鏈接,而不是符號鏈接(它只不過是指向現有路徑的指針,而不是您想要的)。

編輯:

ln /proc/... /tmp/...命令無法工作,因為 /proc 和 /tmp 位於不同的檔案系統中。不幸的是,我不知道有什麼方法可以為現有的索引節點建立路徑名。人們可能希望link()系統呼叫採用索引節點號和路徑,但它採用來源路徑和目標路徑。

相關內容