rm -rf ile silinen dosyalar nasıl kurtarılır?
rm -rf komutuyla silinen verileri kurtarmak için disk yazma işlemlerini hemen durdurun. ext4 dosya sisteminde veri kaybını önleme ve kurtarma yöntemlerini adım adım inceleyin.
İlk altmış saniyede yapılması gerekenler
rm -rf ile silinen dosyaları kurtarıp kurtaramayacağınızı iki faktör belirler ve her ikisi de bir arama motoru açmadan önce gerçekleşir. İlgili dosya sistemine yazma işlemini durdurun. Ardından, dosya sistemini unmount ederek veya salt okunur (read-only) modda yeniden mount ederek kullanım dışı bırakın.
rm hiçbir şeyi silmez. Yalnızca dizin girişini kaldırır, ardından inode ve dosyanın veri bloklarını boş olarak işaretler. Baytlar cihaz üzerinde durmaya devam eder. Blok ayırıcı bu blokları başka bir işleme atayana ve o işlem üzerine yazana kadar veriler orada kalır. Dosya sistemi mount edilmiş ve meşgul durumda kaldığı her saniye, bir daemon günlük kaydı yazar veya bir veritabanı sayfa temizliği yapar; bu yazma işlemlerinden herhangi biri geri almak istediğiniz blokların üzerine gelebilir.
Bu nedenle ilk komutlar, dosyaları kurtaranlar değil, yazma işlemlerini durduranlardır.
sudo systemctl stop nginx postgresql
sudo umount /mnt/dataEğer umount, umount: /mnt/data: target is busy. yanıtını veriyorsa, dosya sistemini neyin açık tuttuğunu bulun.
sudo fuser -vm /mnt/data
sudo lsof +D /mnt/dataEğer serbest bırakamıyorsanız, bunun yerine salt okunur modda yeniden mount edin. Salt okunur mount işlemi, ihtiyaç duyduğunuz şeyin büyük kısmını karşılayarak yeni blok tahsislerini durdurur.
sudo mount -o remount,ro /mnt/dataEğer silinen yol kök (root) dosya sistemi üzerindeyse, bu işlem daha zordur. sudo mount -o remount,ro / genellikle mount: /: cannot remount /dev/vda1 read-only. hatasıyla başarısız olur; çünkü çalışan süreçler dosyaları yazma modunda açık tutar ve çekirdek bunları zorla kapatmaz. Bir VPS üzerinde pratik çözüm, sağlayıcınızın kurtarma (rescue) modudur: bu mod, diskinizi bağlı ancak mount edilmemiş şekilde tutan ayrı bir canlı sistem başlatır. Aşağıdaki her komut, üzerinde kimsenin yazma yapmadığı bir cihaz üzerinde çalıştırılmalıdır.
Bu kılavuzun tamamı için tek bir kural geçerlidir. Kurtarılan dosyaları, disk imajını veya yeni yüklenen bir aracı asla kurtarma yaptığınız dosya sistemine yazmayın. İkinci bir birim bağlayın veya çıktıyı SSH üzerinden başka bir makineye gönderin.
ext4 üzerinde rm -rf kurtarma işleminin neden çoğunlukla sonuçsuz olduğu
Herhangi bir şey kurmadan önce beklentilerinizi belirleyin. Hangi dosya sistemiyle çalıştığınızı doğrulayın:
lsblk -fNeredeyse tüm VPS imajlarında varsayılan olan ext4 üzerinde, bir dosyanın veri konumu, inode içerisinde bir extent ağacı olarak tutulur. Bir extent, bu dosyanın mantıksal N bloğunun fiziksel M bloğunda başladığını ve L blok boyunca devam ettiğini belirten bir kayıttır. Küçük dosyalar bu kayıtlardan dördünü inode içinde tutar. Daha büyük dosyalar ise ağacın geri kalanını barındıran ek bloklara işaret eder.
Bir dosyaya giden son bağlantı kaldırıldığında, ext4 bu ağacı tarar, her extent kaydını blok ayırıcıya geri verir ve ağacı inode içinden temizler. Inode daha sonra boş olarak işaretlenir ve üzerine bir silinme zamanı damgası basılır. Verinin kendisi ise olduğu gibi kalır. Verinin nerede olduğuna dair tek kayıt silinmiş olur.
Bu durum, silinen bir inode'un ext3grep gibi bir aracın takip edebileceği kadar bilgiyi geride bıraktığı ext3'ten farklıdır. ext4 üzerinde silinen inode'ları hala listeleyebilirsiniz:
sudo debugfs -R lsdel /dev/vdb1debugfs, -w bayrağını geçmediğiniz sürece aygıtı salt okunur olarak açar; bu nedenle, bağlanmamış (unmounted) bir aygıtta bu işlem güvenlidir ve denemenin bir maliyeti yoktur. Inode'lar listelenecektir. Ancak bir inode'un içeriğini dökmek (dump) yolun sonudur, çünkü o inode'un daha önce tuttuğu blok haritası temizlenmiştir ve dump aracının takip edebileceği hiçbir şey kalmamıştır.
İki araç, journal (günlük) dosyasını okuyarak bu durumu aşmaya çalışır. Journal, ext4'ün bir çökme anında meta verilerin tutarlılığını sağlamak için kullandığı sabit boyutlu bir döngüsel yapıdır ve silme işleminden önceki inode'un eski bir kopyasını hala barındırıyor olabilir. extundelete ve ext4magic araçlarının her ikisi de bu alanda arama yapar. Hangi boyutla çalıştığınızı kontrol edin:
sudo dumpe2fs -h /dev/vdb1 | grep -i journalJournal yalnızca meta verileri tutar ve boyutu küçüktür; bu nedenle normal yazma işlemleri bu alanı hızla döngüsel olarak tüketir. Çalışan bir sunucuda, silme öncesi inode'un hala mevcut olduğu zaman aralığı dakikalarla ölçülür. Her iki araç da aktif olarak geliştirilmemektedir ve her dağıtımda paket olarak bulunmaz. Her ikisini de düşük ihtimalli bir çözüm olarak görün, bunları bağlanmamış bir aygıt veya disk imajı üzerinde çalıştırın ve hiçbir sonuç döndürmediklerinde şaşırmayın.
Eğer lsblk -f, xfs çıktısını veriyorsa durum daha iyi değildir, çünkü XFS için de desteklenen bir "silineni geri getirme" (undelete) yöntemi yoktur. Aşağıdaki seçeneklerin sırası bu durumu değiştirmez.
Dosya çalışan bir süreçte hala açık mı?
Bu yöntem, bu sayfadaki başarı şansı en yüksek kurtarma işlemidir ve dosyayı kullanan servisi yeniden başlatmamanızın temel nedenidir.
Bir dosya, ancak iki sayaç sıfıra ulaştığında gerçekten silinmiş sayılır: inode'u işaret eden dizin girdilerinin sayısı ve açık dosya tanımlayıcılarının (file descriptor) sayısı. rm komutu ilk sayacı sıfıra indirir. Eğer bir süreç dosyayı hala açık tutuyorsa, ikinci sayaç sıfır değildir; bu nedenle inode ve ilgili bloklar hala tahsis edilmiş durumdadır ve veriler okunabilir.
Bağlantı sayısı sıfıra düşmüş açık dosyaları bulun:
sudo lsof +L1+L1, bağlantı sayısı 1'in altında olan açık dosyaları listeler. Her eşleşme; süreci, dosya tanımlayıcı numarasını, 0 içindeki bir NLINK değerini ve (deleted) ile biten bir yolu gösterir. PID ve tanımlayıcı numarasını alarak /proc dizinine gidin:
sudo ls -l /proc/1234/fdBir girdi 3 -> /var/log/app/events.log (deleted) şeklinde görünür. Bu bağlantı veriye hala erişim sağlar. Dosyayı farklı bir dosya sistemine kopyalayın:
sudo cp /proc/1234/fd/3 /mnt/rescue/events.logmv yerine cp kullanın. /proc/1234/fd/3 dosyasını açmak, aynı inode üzerinde sıfır ofsetinden başlayan yeni bir tutamaç sağlar; böylece yazma işleminin o anki konumundan sonrasını değil, dosyanın tamamını alırsınız.
Bilmeniz gereken iki sınırlama vardır. Silinen bir dizin ağacı bu yöntemle geri getirilemez, çünkü yalnızca sürecin açık tuttuğu bireysel dosyalar korunur. Ayrıca, veritabanı motoru yazma işlemi yaparken kopyalanan bir veritabanı dosyası "crash-consistent" (çökme sonrası tutarlı) bir kopyadır; bu nedenle dosyayı temiz kabul etmek yerine veritabanı motorunun kendi kurtarma araçlarını çalıştırmayı planlayın. lsof çıktısında tanımlayıcı numarası yerine mem görünen girdiler belleğe eşlenmiştir (memory mapped) ve bunların kopyalanabileceği bir /proc/<pid>/fd girdisi bulunmaz.
btrfs, ZFS veya LVM üzerinde snapshot'ınız var mı?
Dosya sistemi snapshot alıyorsa, silinen dosyalar zaten bir tanesinin içinde değişmemiş halde duruyordur. Bu yöntem yalnızca silme işleminden önce bir snapshot alınmışsa işe yarar. Şu an oluşturacağınız hiçbir şey geçmişe dönük bir kurtarma sağlamaz.
btrfs, snapshot'ları subvolume olarak tutar:
sudo btrfs subvolume list /Snapshot'a göz atın ve ihtiyacınız olan yolları cp -a ile kopyalayın. Tüm subvolume'u geri yüklemek yerine tekil yolları kopyalamayı tercih edin; çünkü geri yükleme işlemi, snapshot alındıktan sonra yazılan her şeyi de siler.
ZFS, her snapshot'ı salt okunur bir dizin olarak sunar:
zfs list -t snapshot
ls /tank/data/.zfs/snapshot/.zfs dizini gizlidir ve veri kümesi kök dizininde yapılan düz bir ls komutunda görünmez, ancak dizin adını yazarak içine girebilirsiniz. Dosyaları oradan kopyalayın. zfs rollback tüm veri kümesini geri alır ve belirttiğinizden daha yeni olan tüm snapshot'ları yok eder, bu yüzden bunu son çare olarak saklayın.
LVM snapshot'ları, sabit boyuta sahip copy-on-write birimleridir:
sudo lvs
sudo mount -o ro /dev/vg0/data-snap /mnt/snapSnapshot'ı salt okunur olarak mount edin ve dosyaları kopyalayın. Güvenmeden önce lvs komutuyla kontrol edin; çünkü ayrılan alanı dolan bir LVM snapshot'ı çekirdek tarafından geçersiz kılınır ve bu gerçekleştiğinde içeriği tamamen kaybolur.
Snapshot bir yedekleme değildir. Orijinal veri ile aynı diskte veya aynı havuzda bulunur, bu nedenle orijinalin yaşadığı her türlü arızadan etkilenir. İki dakika önce yapılan bir hatayı geri almak için çok uygundur ve buradaki görev tam olarak budur.
PhotoRec ile veri kurtarma: Canlı disk yerine imaj dosyası üzerinde işlem yapın
Yukarıdakilerin hiçbiri çözüm sağlamıyorsa geriye kalan tek yöntem veri kurtarmadır (carving): Ham cihazı, bilinen bir dosya türünün başlangıcını işaret eden bayt dizileri için taramak ve ardından takip eden veriyi yazmaktır. Veri kurtarma işlemi yalnızca dosya verisini okur. Dosya adları, dizin yapısı, zaman damgaları ve sahiplik bilgileri dosya sistemi meta verileridir; rm bu meta verileri yok ettiği için bunların hiçbiri geri gelmez. Numaralandırılmış bir çıktı dizininde f0384512.jpg adıyla dosyalar elde edersiniz ve bunları elle ayıklamanız gerekir.
Bu yöntemin işe yarayıp yaramayacağına iki kural karar verir.
Birincisi, başka bir işlem yapmadan önce cihazın imajını alın. Debian ve Ubuntu üzerinde paket gddrescue, yüklediği ikili dosya ise ddrescue'tür.
sudo apt update && sudo apt install -y gddrescue testdisk
sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map/mnt/rescue, bölümün kapladığı alan kadar boş alana sahip farklı bir cihazda bulunmalıdır. lsblk -b, tam boyutları bayt cinsinden yazdırır. Harita dosyası, kesintiye uğrayan bir kopyalama işleminin baştan başlamak yerine kaldığı yerden devam etmesini sağlar. İmajı aldıktan sonra, ilk araç diskin üzerine yazmış olsaydı yapamayacağınız şekilde, aynı baytlar üzerinde ikinci bir aracı daha sonra deneyebilirsiniz.
İkincisi, kurtarma aracını imaj dosyasına yönlendirin.
sudo photorec /d /mnt/rescue/recup /mnt/rescue/vdb1.imgphotorec bir metin menüsü açar. Bölümü, ardından dosya sistemi türünü, aranacak dosya imzalarını ve son olarak hedef dizini seçin. Başlamadan önce imza listesini gerçekten kaybettiğiniz dosya türleriyle sınırlandırın; çünkü varsayılan liste her şeyi bulur ve size ayıklamanız gereken on binlerce parça sunar.
Aynı pakette bulunan testdisk, kendi silinenleri geri getirme işlevine sahiptir ve yalnızca FAT, exFAT, NTFS ve ext2 dosya sistemlerini kapsar. ext4 üzerinde ise geriye photorec kalır.
Parçalanmış dosyaların bozuk geleceğini göz önünde bulundurun. Veri kurtarma, bir dosyanın bloklarının ardışık olduğunu varsayar; bu nedenle ayırıcının diske dağıttığı bir dosya ya yanlış birleştirilir ya da tamamen gözden kaçırılır. Medya dosyaları güçlü başlıklara sahip oldukları için nispeten iyi kurtarılır. Düz metin, yapılandırma dosyaları ve kaynak kodları ise kötü kurtarılır; çünkü bir shell betiğinin başlangıcını işaret eden belirgin bir bayt imzası yoktur.
Fazladan boşluk: yanlış yol nasıl silindi
Neredeyse her rm -rf kazası bir kabuk (shell) sorunudur. rm bir yol listesi alır ve her birini sırayla siler. Sizin neyi kastettiğinizi asla anlamaz.
Klasik hata tek bir boşluktur:
rm -rf /home/deploy/app /old
rm -rf /home/deploy/app/oldİlk satır iki argümandan oluşur. Önce uygulamayı siler, ardından /old dizinini siler. Eğer /old mevcut değilse, rm hiçbir çıktı vermez; çünkü -f eksik dosya hatasını bastırır. Sessizlik, işlemin onaylandığı anlamına gelmez.
İkinci biçim, içinde boşluk karakteri barındıran tırnak içine alınmamış bir değişkendir:
dir="/srv/my app"
rm -rf $dirKabuk, değeri boşluk karakterine göre ayırır; bu nedenle rm, /srv/my ve app değerlerini iki ayrı yol olarak alır. rm -rf "$dir" şeklinde yazıldığında ise tek bir yol olarak algılanır.
Üçüncüsü ise, genellikle onu doldurması gereken komut başarısız olduğu için boş kalan bir değişkendir:
rm -rf "$TARGET"/*TARGET tanımlanmadığında, bu ifade rm -rf /* şeklinde genişler. GNU rm, çıplak biçimi reddeder: rm -rf /, rm: it is dangerous to operate recursively on '/' çıktısını verir ve durur. Glob biçimi ise böyle bir korumaya sahip değildir; çünkü kabuk, rm çalışmadan önce /* ifadesini gerçek üst düzey yolların listesiyle değiştirir. / bu listede yer almadığı için koruma mekanizması asla devreye girmez.
Bir sonraki hatayı önleyen alışkanlıklar
- Yol olarak kullanılan her değişkeni tırnak içine alın. Testler ve döngüler dahil olmak üzere her seferinde
"$dir"yazın. - Boş değerde işlemi durdurun.
rm -rf "${TARGET:?TARGET is not set}"/*,TARGETayarlanmamış veya boş olduğunda,rmbaşlamadan önce kabuğun mesajınızla durmasını sağlar. Silme işlemi yapan her betiğin en üstüneset -euo pipefailekleyin. --one-file-systemekleyin. Bu komut,rmaracına, verdiğiniz argümandan farklı bir dosya sisteminde bulunan dizinleri atlamasını söyler; böylece özyinelemeli bir silme işlemi, bağlı bir yedekleme birimine veya bind mount noktasına sızamaz.- root kullanıcısı olarak silme yapmayın. Bir servis hesabı yalnızca sahip olduğu verileri yok edebilir; bu durum her servisi kendi yetkisiz kullanıcısı ile çalıştırmanın temel gerekçesidir. Belirli bir hesabın nerelere erişebileceğinden emin değilseniz, ls çıktısındaki izin bitlerini okumak bunu tek komutla yanıtlar.
- İşlem yapmadan önce listeyi yazdırın. Bir betik içinde yolları oluşturun,
printf '%s\n'ile listeleyin, çıktıyı okuyun ve ardından ikinci bir geçişte silme işlemini gerçekleştirin. - Elinizin altında bir çöp kutusu komutu bulundurun.
sudo apt install trash-clisizetrash-put,trash-list,trash-restorevetrash-emptyaraçlarını sağlar. Silinen dosyalar~/.local/share/Trashdizinine taşınır vetrash-empty 30komutu otuz günden eski olan her şeyi temizler.
rm komutunu trash-put olarak alias yapmak, bir sonraki mantıklı adım gibi görünür ancak bu bir tuzaktır. Bu alias, üzerinde bu ayarın bulunmadığı bir sonraki sunucuda başarısız olacak bir refleks oluşturur; ayrıca alias tanımları, pahalı hataların yapıldığı yer olan betiklerin içinde geçerli değildir. Bunun yerine trash-put komutunu bilerek yazın.
Her zaman çalışan tek kurtarma yöntemi
Yukarıda bahsedilen her şey bir ihtimaldir. Yedekleme ise bir ihtimal değildir.
Bir yedeklemeyi gerçek kılan iki unsur vardır. Yedekleme, siz hatırlamanıza gerek kalmadan bir zaman çizelgesine göre çalışır ve siz bu yedekten en az bir kez geri yükleme yapmışsınızdır. Daha önce hiç geri yükleme yapılmamış bir depo sadece bir inançtır; çünkü onu işe yaramaz hale getiren unsurlar (dahil etme listesindeki yanlış bir yol veya kimsenin not almadığı bir depo parolası) ancak ona ihtiyaç duyduğunuz gün ortaya çıkar.
restic ile geri yükleme yapmak iki komuttur.
restic -r /srv/restic-repo snapshots
restic -r /srv/restic-repo restore latest --target /mnt/rescue --include /srv/appdataCanlı yolun üzerine yazmak yerine boş bir dizine geri yükleme yapın; böylece hiçbir şey yerini almadan önce ikisini karşılaştırabilirsiniz. Bir VPS üzerinde restic yedeklerini yapılandırma rehberi, depo kurulumunu ve bunu çalıştıran systemd zamanlayıcısını kapsar.
Borg ile:
borg list /srv/borg-repo
borg extract /srv/borg-repo::daily-2026-08-08 srv/appdataBorg arşivindeki yollar başında eğik çizgi (slash) olmadan saklanır, bu nedenle srv/appdata eşleşir ancak /srv/appdata hiçbir şeyle eşleşmez. borg extract mevcut çalışma dizinine yazar, bu yüzden önce cd ile geçici bir dizine geri yükleme yapın.
Henüz ikisi arasında bir seçim yapmadıysanız, restic ve Borg karşılaştırması rehberi, veri tekilleştirme ve sadece ekleme yapılabilen (append-only) depoları kapsar; bu özellik, güvenliği ihlal edilmiş bir sunucunun kendi yedekleme geçmişini silmesini engeller. Her iki araç da uygundur. Yanlış olan tek cevap, hiçbirinin çalışmıyor olmasıdır.
Yeni bir sunucu, üzerinde kaybedilmeye değer hiçbir şey yokken bu kurulumu yapmak için en ucuz zamandır. Yeni bir VPS üzerindeki ilk on dakika rehberi, SSH ve güvenlik duvarı kurulumuyla birlikte bu işin yapılması gereken yerdir.
Ardından takviminize düzenli bir kayıt ekleyin: her ay depodan bir dizini /tmp dizinine geri yükleyin ve dosyaları okuyun. Bu tek alışkanlık, bu sayfadaki tüm araçlardan daha değerlidir.
FAQ
ext4 üzerinde silinen bir dosyayı geri getirebilir miyim?
Genellikle hayır. Bir dosyaya ait son bağlantı silindiğinde, ext4 inode içerisindeki extent ağacını temizler; bu nedenle disk üzerinde verinin nerede olduğuna dair hiçbir kayıt kalmaz. extundelete ve ext4magic araçları, ext4 günlüğünde (journal) inode'un eski bir kopyasını arar; bu yöntem yalnızca silme işlemi birkaç dakika önce gerçekleştiyse ve dosya sistemi o andan itibaren boşta kaldıysa işe yarar. Her iki proje de aktif olarak geliştirilmemektedir. Bu araçları asla bağlı (mounted) bir dosya sistemi üzerinde çalıştırmayın; mutlaka bağlı olmayan bir aygıt veya disk imajı üzerinde kullanın. İşlem yapmadan önce sudo dumpe2fs -h /dev/vdb1 | grep -i journal ile üzerinde çalıştığınız aygıtı doğrulayın.
Bir servis silinen dosyayı hala açık tutuyor. Geri alabilir miyim?
Evet, bu en iyi senaryodur. Bir süreç dosyayı açık tuttuğu sürece, dosyanın inode ve veri blokları tahsis edilmiş durumda kalır; dolayısıyla veriler hala okunabilir. Servisi yeniden başlatmayın, çünkü son dosya tanımlayıcısının (file descriptor) kapatılması silme işlemini tamamlar. Bağlantı sayısı 0 olan açık dosyaları listelemek için sudo lsof +L1 komutunu çalıştırın, PID ve dosya tanımlayıcı numarasını not edin, ardından sudo cp /proc/1234/fd/3 /mnt/rescue/events.log kullanarak /proc üzerinden kopyalayın. Kopyayı farklı bir dosya sistemine yazın. Dosya tanımlayıcı numarası yerine mem ile gösterilen girdiler belleğe eşlenmiştir (memory mapped) ve kopyalanabilecek bir /proc/<pid>/fd yolu bulunmaz.
Neden kurtarma aracını doğrudan disk üzerinde çalıştırmak yerine imajını almalıyım?
Çünkü her araç çıktısını bir yere yazmak zorundadır ve kurtarmaya çalıştığınız dosya sistemine yapılacak bir yazma işlemi, verilerinizin hala bulunduğu boş blokların üzerine yazılmasına neden olabilir. Önce sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map ile bölümü farklı bir aygıta kopyalayın, ardından photorec aracını imaj dosyasına yönlendirin. İmaj dosyası, aynı baytlar üzerinde daha sonra ikinci bir aracı denemenize olanak tanır; orijinal disk üzerinde bir kez yazma yapıldığında bu imkansız hale gelir.
rm -rf / komutu hala bir Linux sistemini yok eder mi?
Komutun yalın hali yok etmez. GNU rm bu komutu reddeder ve rm: it is dangerous to operate recursively on '/' çıktısını verir. Tehlikeli olan, başka yollarla gelen komut biçimleridir. TARGET tanımlanmamışken (unset) kullanılan rm -rf "$TARGET"/*, rm -rf /* şeklinde genişler. Kabuk (shell), rm komutuna en üst düzey dizinlerin bir listesini iletir; bunların hiçbiri / olmadığı için koruma mekanizması tetiklenmez. Bunun yerine "${TARGET:?TARGET is not set}" yazın; böylece rm çalışmadan önce kabuk işlemi durduracaktır.
Dosya sistemi anlık görüntüsü (snapshot) bir yedek midir?
Hayır. Bir btrfs veya ZFS anlık görüntüsü, koruduğu verilerle aynı havuzda (pool) bulunur; bu nedenle disk arızası veya havuzun bozulması her ikisini de aynı anda yok eder. LVM anlık görüntüsünün ise sabit boyut sorunu vardır: dolduğunda çekirdek onu geçersiz kılar ve içeriği kaybolur. Anlık görüntüler, iki dakika önce yapılan bir silme işlemini geri almak için mükemmeldir. Diğer tüm durumlar için verileri ayrı bir donanım üzerinde depolayın.