Linux中多進程環境下,打開同一個文件,當一個進程進行讀寫操作,如果另外一個進程刪除了這個文件,那麼讀寫該文件的進程會發生什麼呢?
- 因爲文件被刪除了,讀寫進程發生異常?
- 正在讀寫的進程仍然正常讀寫,好像沒有發生什麼?
學操作系統原理的時候,我們知道,linux是通過link的數量來控制文件刪除,只有當一個文件不存在任何link的時候,這個文件纔會被刪除。
而每個文件都會有2個link計數器i_count 和 i_nlink。i_count的意義是當前使用者的數量,也就是打開文件進程的個數。i_nlink的意義是介質連接的數量;或者可以理解爲 i_count是內存引用計數器,i_nlink是硬盤引用計數器。再換句話說,當文件被某個進程引用時,i_count 就會增加;當創建文件的硬連接的時候,i_nlink 就會增加。
對於 rm 而言,就是減少 i_nlink。這裏就出現一個問題,如果一個文件正在被某個進程調用,而用戶卻執行 rm 操作把文件刪除了,會出現什麼結果呢?
當用戶執行 rm 操作後,ls 或者其他文件管理命令不再能夠找到這個文件,但是進程卻依然在繼續正常執行,依然能夠從文件中正確的讀取內容。這是因爲,rm 操作只是將 i_nlink 置爲 0 了;由於文件被進程引用的緣故,i_count 不爲 0,所以系統沒有真正刪除這個文件。i_nlink 是文件刪除的充分條件,而 i_count 纔是文件刪除的必要條件。
基於以上只是,大家猜一下,如果在一個進程在打開文件寫日誌的時候,手動或者另外一個進程將這個日誌刪除,會發生什麼情況?
雖然日誌文件被刪除了,但是有一個進程已經打開了那個文件,所以向那個文件中的寫操作仍然會成功,數據仍然會提交。
下面,告訴大家如何恢復那個刪除的文件。
例如,你刪除了tcpdump.log,執行lsof | grep tcpdump.log,你應該能看到這樣的輸出:
tcpdump 2864 tcpdump 4w REG 253,0 0 671457 /root/tcpdump.log (deleted)
然後:
cp /proc/2864/fd/4 /root/tcpdump.log