Arka plan: Fiziksel sunucu, yaklaşık iki yaşında, 3Ware RAID karta bağlı 7200 RPM SATA sürücüler, ext3 FS'ye monte edilmiş bir zaman dilimi ve veri = sipariş edildi, çılgın yük altında değil, çekirdek 2.6.18-92.1.22.el5, çalışma süresi 545 gün . Dizin, daha büyük (birkaç KB) dosya içeren milyonlarca küçük (~ 100 byte) dosya içeren herhangi bir alt dizin içermez.
Son birkaç ay boyunca biraz guguklandıran bir sunucumuz var, ancak geçen gün sadece çok fazla dosya içerdiği için bir dizine yazamaya başladığını fark ettik. Özellikle, bu hatayı / var / log / messages içine atmaya başladı:
ext3_dx_add_entry: Directory index full!
Söz konusu diskte kalan çok sayıda düğüm var:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
Dolayısıyla, bunun dizin dosyasında kaç giriş olabileceğinin sınırına ulaştığımız anlamına geldiğini tahmin ediyorum. Ne kadar dosya olacağı hakkında hiçbir fikrim yok, ancak görebileceğiniz gibi, üç milyondan fazla olamaz. Bu iyi değil, dikkat et! Ama bu sorumun bir parçası: tam olarak bu üst sınır nedir? Ayarlanabilir mi? Ben bağırdı önce at-ı ayar bunu istiyorum aşağı ; Bu devasa dizin her türlü soruna yol açtı.
Neyse, tüm bu dosyaları oluşturan koddaki sorunu tespit ettik ve düzelttik. Şimdi dizini silmeme şaşırdım.
Burada birkaç seçenek:
rm -rf (dir)
Bunu önce denedim. Kesin bir etkisi olmadan bir buçuk gün çalıştıktan sonra pes ettim ve onu öldürdüm.
- Dizinde unlink (2): Kesinlikle dikkate değer, ancak soru, fsck ile dizindeki dosyaları silmenin unlink (2) ile silmekten daha hızlı olup olmayacağıdır. Yani, öyle ya da böyle, bu düğümleri kullanılmamış olarak işaretlemeliyim. Bu, elbette fsck’e girişleri / kayıp + bulunan dosyalara bırakmamasını söyleyebilir; Aksi takdirde, sorunumu yeni çözdüm. Diğer tüm kaygılara ek olarak, bu konuyu biraz daha okuduktan sonra, bulabileceğim unlink (2) türevlerinin hiçbiri sadece blithly silmeme izin vermeyeceğinden muhtemelen bazı iç FS işlevlerini çağırmak zorunda kalacağım ortaya çıktı. girişleri olan bir dizin. Pooh.
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
Bu aslında kısaltılmış versiyonu; Çalıştırmakta olduğum gerçek, sadece biraz ilerleme bildiren ve silmek için dosyalarımız bittiğinde temiz bir durma sağlayan:
ihracat i = 0; zaman (iken [gerçek]; yap ls -Uf | kafa -n 3 | grep -qF '.png' || break; ls -Uf | kafa -n 10000 | xargs rm -f2> / dev / null; dışa aktarma i = $ (($ i + 10000)); echo "$ i ..."; bitti)
Bu oldukça iyi çalışıyor gibi görünüyor. Bunu yazarken, son otuz dakika içinde 260.000 dosyayı silmiş.
- Yukarıda belirtildiği gibi, dizin başına giriş sınırı ayarlanabilir mi?
- Listenin başında gelen ilk dosya olan tek bir dosyayı silmek neden "gerçek 7m9.561s / kullanıcı 0m0.001s / sys 0m0.001s"
ls -U
aldı ve ilk 10.000 girişi silmek Komuta # 3'te, ama şimdi oldukça mutlu bir şekilde hareket ediyor mu? Bu nedenle, yaklaşık otuz dakikada 260.000 sildi, ancak şimdi 60.000 daha fazla silmek için on beş dakika daha sürdü. Neden dev hızda sallanıyor? - Böyle bir şey yapmanın daha iyi bir yolu var mı? Bir dizinde milyonlarca dosya saklamayın; Aptalca olduğunu biliyorum ve saatimde olmazdı. Sorunun googling edilmesi ve SF ve SO'lara
find
bakılması, bazı belirgin nedenlerden dolayı benim yaklaşımımdan önemli ölçüde daha hızlı olmayacak birçok değişiklik sunar . Ancak fsck yoluyla silme fikrinin herhangi bir ayağı var mı? Ya da tamamen başka bir şey? Kutudan çıkma (ya da tanınmayan kutunun içi) düşüncesini duymak için sabırsızlanıyorum.
Son senaryo çıktısı !:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
Böylece, üç milyon dosya dört saatten biraz daha fazla bir sürede silindi.
rm -rfv | pv -l >/dev/null
. pv, EPEL deposunda mevcut olmalıdır .