程序打開了不在任何文件系統上的inode?
所以我試圖找出
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
所以我可以看到
stdout
和stderr
(文件描述符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 編號和路徑,但它採用源路徑和目標路徑。