Bir dosya silinmiş ancak yine de açıksa, dosya dosya sisteminde hala var demektir (bir inode vardır ) ancak sabit bağlantı sayısı 0'dır. Dosyaya bağlantı olmadığından dosyayı adıyla açamazsınız . Dosyayı inode ile açmak için herhangi bir olanak yoktur.
Dosyayı dosya sistemi aracılığıyla keşfetmenin bir yolu yoktur ve özellikle dosyayı en son bulunduğu dizinde aramanın bir yolu yoktur. Dizin girişi gitti. Geriye kalan tek şey dosyanın kendisidir. Bir dosya sistemi hata ayıklayıcı ile dosyaya ulaşabilirsiniz, ancak bu kök izinleri gerektirir ve kullanımı zordur ve hataya açıktır.
Linux açık dosyaları, altındaki özel sembolik bağlantılar aracılığıyla ortaya koyar /proc
. Bu bağlantılara /proc/12345/fd/42
12345 bir işlemin PID'si ve 42 ise bu işlemdeki bir dosya tanımlayıcı sayısı olarak adlandırılır . Bu işlemle aynı kullanıcıyla çalışan bir program dosyaya erişebilir (okuma / yazma / yürütme izinleri dosya silindiği zamankiyle aynıdır).
Dosya açıldı altında adı hala sembolik bağın hedefi görülebilir: Dosya olsaydı /var/log/apache/foo.log
, o zaman bağlantının hedefidir /var/log/apache/foo.log (deleted)
. (Dosya açıldıktan sonra yeniden adlandırıldıysa, sembol bağlantısının hedefi yeniden adlandırmayı yansıtabilir.)
Böylece, açık olan bir işlemin PID'si ve açıldığı açıklayıcı gibi açık silinen bir dosyanın içeriğini kurtarabilirsiniz:
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"
Yalnızca işlem kimliğini biliyor ancak tanımlayıcıyı bilmiyorsanız, tüm dosyaları
for x in /proc/$pid/fd/*; do
recover_open_deleted_file "$x"
done
İşlem kimliğini de bilmiyorsanız, tüm işlemler arasında arama yapabilirsiniz:
for x in /proc/[1-9]*/fd/*; do
case $(readlink "$x") in
/var/log/apache/*) recover_open_deleted_file "$x";;
esac
done
Bu listeyi çıktısını ayrıştırarak da alabilirsiniz lsof
, ancak daha basit, daha güvenilir veya daha taşınabilir değildir (bu yine de Linux'a özgüdür).
lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'