Linux

恢復被apache打開的已刪除文件?

  • May 13, 2016

假設一個 apache 日誌文件被刪除但它被 apache 保持打開;那麼這就是我正在做的事情:

pid=$(lsof | grep text.txt | awk '/deleted/ {print $2}')
fd=$(lsof | grep text.txt | awk '/deleted/ {print $4}' | grep -oE "[[:digit:]]{1,}")

cp /proc/$pid/fd/$fd directorytobecopied/testfile.txt

這就是我正在做的恢復文件並將其放回原處的方法。有沒有更簡單的方法可以做到這一點,因為上面的程式碼看起來不太好。此外,我如何知道文件是從哪裡刪除的(directorytobecopied),這樣我就不必手動詢問文件的原始位置並將其放回原處。

如果文件已被刪除但仍處於打開狀態,則意味著該文件仍存在於文件系統中(它有一個inode)但硬連結計數為 0。由於沒有指向該文件的連結,因此您無法通過名稱打開它. 也沒有通過 inode 打開文件的功能。

無法通過文件系統發現文件,尤其是無法在文件最後所在的目錄中查找文件。目錄條目不見了。剩下的就是文件本身。您可以使用文件系統調試器訪問該文件,但這需要 root 權限並且難以使用且容易出錯。

Linux 通過/proc. 呼叫這些連結,/proc/12345/fd/42其中 12345 是程序的 PID,42 是該程序中文件描述符的編號。以與該程序相同的使用者身份執行的程序可以訪問該文件(讀/寫/執行權限與刪除文件時的權限相同)。

打開文件的名稱在符號連結的目標中仍然可見:如果文件是/var/log/apache/foo.log,則連結的目標是/var/log/apache/foo.log (deleted)。(如果文件在打開後被重命名,則符號連結的目標可能會反映重命名。)

因此,您可以在給定打開文件的程序的 PID 和打開它的描述符的情況下恢復打開的已刪除文件的內容,如下所示:

recover_open_deleted_file () {
 old_name=$(readlink "$1")
 case "$old_name" in
   *' (deleted)')
     old_name=${old_name%' (deleted)'}
     if [ -e "$old_name" ]; then
       new_name=$(TMPDIR=${old_name%/*} mktemp)
       echo "$oldname has been replaced, recovering content to $new_name"
     else
       new_name="$old_name"
     fi
     cat <"$1" >"$new_name";;
   *) echo "File is not deleted, doing nothing";;
 esac
}
recover_open_deleted_file "/proc/$pid/fd/$fd"

如果您只知道程序 ID 而不是描述符,則可以使用以下命令恢復所有文件

for x in /proc/$pid/fd/*; do
 recover_open_deleted_file "$x"
done

如果您也不知道程序 ID,則可以在所有程序中搜尋:

for x in /proc/[1-9]*/fd/*; do
 case $(readlink "$x") in
   /var/log/apache/*) recover_open_deleted_file "$x";;
 esac
done

您也可以通過解析 的輸出來獲取此列表lsof,但它並不簡單、更可靠、更便攜(無論如何這是 Linux 特定的)。

引用自:https://unix.stackexchange.com/questions/58949