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:
- Bağlantı sayısı sıfıra düşmüştür.
- 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.
rmdiryalnızca boş dizinleri siler ve bu başarısızlık bir güvenlik ölçütüdür;rm -riçeriğiyle birlikte siler.-fonay sormayı ve var olmayan dosya hatasını kapatır; silme yetkisi kazandırmaz.- Yıkıcı bir komutun başına
echoyazmak, kabuğun üreteceği argüman listesini sonuç doğurmadan gösterir. -iher dosyada,-Itoplu işlemde bir kez sorar;-Itaşı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.