恢復被apache打開的已刪除文件?
假設一個 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 特定的)。