mun*_*ish 10 linux shell logs data-recovery apache-httpd
假设一个 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
Run Code Online (Sandbox Code Playgroud)
这就是我为恢复文件并将其放回原处所做的工作。有没有更简单的方法来做到这一点,因为上面的代码看起来不太好。此外,我如何知道文件被删除的位置(directorytobecopied),以便我不必手动询问某人文件的原始位置并将其放回那里。
Gil*_*il' 15
如果文件已被删除但仍处于打开状态,则表示该文件仍存在于文件系统中(它有一个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"
Run Code Online (Sandbox Code Playgroud)
如果您只知道进程 ID 但不知道描述符,则可以使用以下命令恢复所有文件
for x in /proc/$pid/fd/*; do
recover_open_deleted_file "$x"
done
Run Code Online (Sandbox Code Playgroud)
如果您也不知道进程 ID,则可以在所有进程中搜索:
for x in /proc/[1-9]*/fd/*; do
case $(readlink "$x") in
/var/log/apache/*) recover_open_deleted_file "$x";;
esac
done
Run Code Online (Sandbox Code Playgroud)
您也可以通过解析 的输出来获取此列表lsof,但它既不简单,也不可靠,也不可移植(无论如何,这是特定于 Linux 的)。