apache tarafından açık tutulan silinen dosyayı kurtarma?


10

Bir apache günlük dosyasının silindiğini ancak apache tarafından açık tutulduğunu varsayalım; o zaman ben bunu yapıyorum:

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

Bu dosyayı kurtarmak ve geri olduğu yere koymak için yapıyorum. Yukarıdaki kod iyi görünmüyor çünkü bunu yapmanın daha basit bir yolu var mı. Dahası, nasıl bir dosyanın el ile orijinal olarak bulunduğu birine sormak ve oraya koymak zorunda kalmamak için dosya silindi ( directorytobecopied ) nereden biliyorum .


lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'
Rahul Patil

Yanıtlar:


14

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/4212345 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).


X'in okuma veya yazma için açık olup olmamasına bakılmaksızın / proc / x / fd / y'yi okuma veya yazma için açabilirsiniz.
Stéphane Chazelas

neden unix işletim sistemi dosya açıkken silinmesine izin veriyor ... pencerelerde
yapamıyoruz.

@munish Windows ortak bir çoklu görev modelinden başladı: bir uygulama hatalı çalışırsa, sistemi düşürebilir. Sorunların çoğu şu ana kadar düzeltildi, ancak Windows hala bir uygulamanın bir dosyayı ele geçirmesine izin veriyor: dosya açık olduğu sürece, yeniden adlandırılamaz veya silinemez. Unix buna izin vermez: bir dosyayı silmek veya yeniden adlandırmak, dosyayı açmaktan dikeydir.
Gilles 'SO- kötü olmayı kes'

1
Muse'un Simetri Kökenini benim için kurtardın! Binlerce kez teşekkür ederim!
dotancohen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.