Apacheで開いた削除されたファイルを復元しますか?

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

ファイルを復元して元の場所に戻そうとする作業です。上記のコードがビューには良くないので、これを行うより簡単な方法はありますか?また、ファイルが削除された場所をどのように知ることができます(コピーするディレクトリ)これで、ファイルが元々どこにあったのかを手動で尋ねて再挿入する必要はありません。

答え1

ファイルが削除されたがまだ開いている場合は、そのファイルがファイルシステムにまだ存在することを意味します。インデックスノード)しかし一つあります。ハードリンク数は0です。ファイルへのリンクがないため、名前で開くことができません。 inodeでファイルを開くツールもありません。

ファイルシステムでは、特にファイルが最後に見つかったディレクトリからファイルを検索することはできません。ディレクトリエントリが消えます。残りはファイル自体だけです。ファイルシステムデバッガを使用してこのファイルにアクセスできますが、root権限が必要で、使いにくく、エラーが発生しやすいです。

Linuxは特別なシンボリックリンクを介して開かれたファイルを公開します/proc。これらのリンクは、/proc/12345/fd/4212345がプロセスの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固有です)。

関連情報