所以我試圖找出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
所以我可以看到stdout
和stderr
(文件描述符 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()
系統呼叫採用索引節點號和路徑,但它採用來源路徑和目標路徑。