ファイルが削除されたがまだ開いている場合、そのファイルはファイルシステムにまだ存在しますが(inodeがあります)、ハードリンクカウントは0です。ファイルへのリンクがないため、名前で開くことはできません。 。iノードでファイルを開く機能もありません。
そのファイルシステムを介してファイルを発見する方法はありません。特に、最後にあったディレクトリでファイルを探す方法はありません。ディレクトリエントリがなくなっています。残っているのはファイル自体だけです。ファイルシステムデバッガーを使用してファイルにアクセスできますが、これには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固有です)。
lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'