İçeriğe geç
academia.sh

Ders 08 / 20

Silme ve Geri Alınamazlık

Silmenin bağ koparma olarak tanımı, açık dosya tanıtıcılarının etkisi, yıkıcı komutlarda doğrulama alışkanlıkları ve tire ile başlayan dosya adlarının tehlikesi.

İçindekiler

Önceki dersin komutları veri kaybettirebiliyordu, ama hepsi bir şeyin üzerine yazarak. Silme doğrudan yok eder ve dosya sisteminde bir “geri al” işlemi yoktur: komut satırından silinen dosya bir çöp kutusuna gitmez.

Bu ders önce silmenin çekirdek düzeyinde ne olduğunu tanımlar — tanım, silinen bir dosyanın neden bazen hâlâ okunabildiğini açıklar — sonra yıkıcı komutlarda uygulanacak doğrulama alışkanlıklarını kurar.

Silmek Bağ Koparmaktır

rm komutunun yaptığı işlem, adından anlaşılandan dardır: dizin girdisini kaldırır. İşlemin sistem çağrısı düzeyindeki adı unlink, yani “bağı kopar”dır.

Her dosyanın üstverisinde bir bağlantı sayısı tutulur; bu, dosyaya işaret eden dizin girdisi sayısıdır. rm bu sayıyı bir azaltır. Veri blokları ancak iki koşul birden sağlandığında serbest bırakılır:

  1. Bağlantı sayısı sıfıra düşmüştür.
  2. Dosyayı açık tutan hiçbir süreç kalmamıştır.

İkinci koşul doğrudan gösterilebilir:

$ printf 'gecici veri\n' > /tmp/gecici.txt
$ exec 3< /tmp/gecici.txt
$ rm /tmp/gecici.txt
$ ls -l /tmp/gecici.txt
ls: cannot access '/tmp/gecici.txt': No such file or directory
$ cat <&3
gecici veri
$ exec 3<&-

Dosya silinmiştir: adı dizinde yoktur, listeleme hata verir. Yine de içeriği okunabilmiştir, çünkü bir dosya tanıtıcısı (file descriptor) onu açık tutmaktadır. Tanıtıcı kapandığı anda veri gerçekten serbest kalır.

Bu davranışın iki pratik sonucu vardır. Birincisi, çalışan bir programın kütük dosyası silindiğinde program yazmayı sürdürür ve disk alanı geri kazanılmaz; alan ancak program yeniden başlatıldığında boşalır. İkincisi, bir programın kullandığı dosyayı silmek onu çökertmez — program dosyayı adıyla değil tanıtıcısıyla kullanır.

Bağlantı sayısı birden büyükse silme veriye hiç dokunmaz; yalnızca adlardan biri gider. Bunun nasıl mümkün olduğu sonraki dersin konusudur.

Dizin Silme

Dizinler iki komutla silinir ve ikisi arasındaki fark bir güvenlik ölçütüdür.

rmdir yalnızca boş dizinleri siler:

$ ls arsiv
ham-p  ham-yedek
$ rmdir arsiv/ham-p
rmdir: failed to remove 'arsiv/ham-p': Directory not empty

rm -r dizini içeriğiyle birlikte, özyinelemeli olarak siler:

$ rm -r arsiv/ham-p
$ ls arsiv
ham-yedek

Önceki derste -p seçeneğinin etkisini göstermek için oluşturulan ikinci yedek böylece kaldırıldı; ham-yedek dizini kalmaya devam ediyor.

rmdir başarısızlığı bir kusur değil, bir özelliktir: dizinin boş olmadığını bildirdiğinde, silinmesi düşünülmemiş içeriğin varlığını haber verir. Bir dizinin boşaltıldığını doğrulamak için rmdir kullanmak, rm -r kullanmaktan güvenlidir.

-f Ne Yapar, Ne Yapmaz

rm var olmayan bir dosya için hata verir ve sıfırdan farklı bir durumla döner:

$ rm /tmp/dnm2/yok.txt
rm: cannot remove '/tmp/dnm2/yok.txt': No such file or directory
$ echo $?
1
$ rm -f /tmp/dnm2/yok.txt
$ echo $?
0

-f seçeneği iki şey yapar: var olmayan dosyalar için hata vermez ve onay sormaz. Silme gücünü artırmaz — silinemeyen bir dosyayı silmez, izinler yine de geçerlidir.

Betiklerde -f sık kullanılır çünkü “zaten yoksa sorun değil” davranışı gerekir. Ancak onay sorularını da kapattığı için, -r ile birleştiğinde en tehlikeli biçime dönüşür.

Doğrulama Alışkanlıkları

Kabuk dersinde kurulan bir olgu burada güvenlik aracına dönüşür: açılımları yapan kabuktur, komut yalnızca sonucu görür. Öyleyse sonuç, komut çalıştırılmadan görülebilir.

$ echo veri/ham/*.csv
veri/ham/olcum-01.csv veri/ham/olcum-02.csv veri/ham/olcum-03.csv
$ echo rm veri/ham/*.csv
rm veri/ham/olcum-01.csv veri/ham/olcum-02.csv veri/ham/olcum-03.csv

İkinci satır, çalıştırılacak komutun tam hâlidir. Silme komutunun başına echo yazıp çıktıyı okumak, deseni yanlış yazmanın bedelini ödemeden hatayı görmeyi sağlar. Yıkıcı bir komutu bu biçimde bir kez çalıştırmak, alışkanlık hâline getirilmesi gereken tek adımlık bir denetimdir.

Deseni ls ile sınamak da aynı işi görür ve dosyaların gerçekten var olduğunu doğrular.

Kabuğun boşlukla bölme kuralı burada kritik hâle gelir. rm veri/ham/*.csv yerine yanlışlıkla rm veri/ham/* .csv yazılırsa — yıldız ile nokta arasında bir boşluk — desen tüm dosyalarla eşleşir ve dizin boşalır. İki komut arasındaki fark tek bir boşluktur; echo ile ön denetim, bu farkı sonuç doğurmadan gösterir.

rm etkileşimli kullanımda iki onay seçeneği sunar:

$ rm -i normal.txt
rm: remove regular empty file 'normal.txt'? n
$ rm -I *.txt
rm: remove 5 arguments? n

-i her dosya için ayrı ayrı sorar ve POSIX’te tanımlıdır. -I yalnızca üçten çok dosya verildiğinde veya -r kullanıldığında bir kez sorar; GNU araçlarına özgüdür ve BSD araçlarında bulunmaz. -I uygulamada daha kullanışlıdır: her dosyada soru sorulması kullanıcıyı otomatik “evet” demeye alıştırır, tek soru ise gerçekten okunur.

Tire ile Başlayan Adlar

Kabuk dersinde tanıtılan -- ayıracının neden gerekli olduğu burada görünür:

$ ls
-kayit.txt  normal.txt
$ rm -kayit.txt
rm: invalid option -- 'k'
Try 'rm ./-kayit.txt' to remove the file '-kayit.txt'.
Try 'rm --help' for more information.
$ rm -- -kayit.txt
$ ls
normal.txt

Komut, tire ile başlayan argümanı seçenek sanmıştır. -- ayıracından sonrası her zaman dosya adı olarak yorumlanır; ./ öneki de aynı işi görür çünkü ad artık tire ile başlamaz.

Bu, teorik bir sorun değildir. Bir desenin böyle bir adla eşleşmesi, komutun beklenmedik seçeneklerle çalışmasına yol açabilir. Betiklerde kullanıcıdan gelen dosya adları her zaman -- ayıracından sonra verilmelidir.

En Yıkıcı Biçim

rm -rf bileşimi, verilen yolun altındaki her şeyi sormadan ve hata bildirmeden siler. Kök dizin üzerinde çalıştırıldığında sistemin tamamını hedefler.

Bu komut bu derste çalıştırılmamıştır ve denenmemelidir. Yaygın araç gerçekleştirimlerinde kök dizin için bir koruma vardır ve komut reddedilir, ancak koruma bir seçenekle devre dışı bırakılabilir ve her sistemde bulunmaz. Asıl tehlike kökün kendisinde de değildir: değişkenin boş kalması durumunda rm -rf "$dizin"/ gibi bir satır kök dizini hedef alır.

Uygulamada üç alışkanlık bu sınıf hataların çoğunu önler:

Mutlak yol yerine dizine girip göreli yolla çalışmak. Yanlış dizindeyken komut ya hata verir ya da dar bir alanı etkiler.

Değişkenli yollarda rm yerine önce echo çalıştırmak. Değişken boşsa bu, çıktıda hemen görünür.

Silmek yerine taşımak. Silinecek içeriği önce bir kenara taşımak, kararın geri alınabilir kalmasını sağlar; taşınan dizin bir süre sonra bilinçli olarak silinir.

Silinen veriyi geri getirmenin sistem düzeyindeki tek güvenilir yolu yedektir. Yedekleme ve anlık görüntü stratejileri Sistem Yönetimi kursunun konusudur; bu kursun kapsamında geri alma yoktur.

Özet

  • Silme dizin girdisini kaldırır ve bağlantı sayısını azaltır; veri, sayı sıfırlanana ve dosyayı açık tutan süreç kalmayana kadar serbest bırakılmaz.
  • rmdir yalnızca boş dizinleri siler ve bu başarısızlık bir güvenlik ölçütüdür; rm -r içeriğiyle birlikte siler.
  • -f onay sormayı ve var olmayan dosya hatasını kapatır; silme yetkisi kazandırmaz.
  • Yıkıcı bir komutun başına echo yazmak, kabuğun üreteceği argüman listesini sonuç doğurmadan gösterir.
  • -i her dosyada, -I toplu işlemde bir kez sorar; -I taşınabilir değildir.
  • Tire ile başlayan dosya adları seçenek sanılır; -- ayıracı veya ./ öneki bunu giderir.

Sonraki Adım

Silmenin tanımı bir soruyu açıkta bıraktı: bağlantı sayısı nasıl birden büyük olabilir, yani bir dosyanın birden çok adı nasıl olur? Sonraki ders bu soruyu yanıtlar ve iki farklı bağlantı türünü — aynı düğümü paylaşan sabit bağ ile bir yol dizesi tutan sembolik bağ — karşılaştırır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat