Solaris

程序打開了不在任何文件系統上的inode?

  • January 20, 2010

所以我試圖找出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/偽/mm@0:null
1:S_IFREG 模式:0640 dev:85,56 ino:26471 uid:0 gid:0 size:10485812
O_WRONLY|O_LARGEFILE
2:S_IFREG 模式:0640 dev:85,56 ino:26471 uid:0 gid:0 size:10485812
O_WRONLY|O_LARGEFILE
3:S_IFCHR 模式:0666 dev:302,0 ino:6815772 uid:0 gid:3 rdev:13,12

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

但是當我查找索引節點號為 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是我的程序打開的 fds。

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

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

(我可以跟踪其中一個 fd 並從中找出它是哪個文件。我問是因為我顯然不了解 fd 和 inode 之間的關係足夠深入)。

因此,我的程序正在寫入某些內容(在某些設備上,使用 inode 26471),然後數據將進入具有不同 inode 編號的文件。誰能給我一個關於這可能是什麼的想法(或者甚至讓我知道我的推理到目前為止是否完全被打破)?

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 位於不同的文件系統中。不幸的是,我不知道為現有 inode 創建路徑名的任何方法。有人會希望link()系統呼叫採用 inode 編號和路徑,但它採用源路徑和目標路徑。

引用自:https://serverfault.com/questions/104577