Sunucuyu rahatsız etmeden milyonlarca dosya nasıl silinir


11

Hızlı bir şekilde temizlediğim bir nginx önbellek dizinini silmek istiyorum:

mv cache cache.bak
mkdir cache
service nginx restart

Şimdi cache.bak2 milyon dosyam var. Sunucuyu rahatsız etmeden silmek istiyorum.

Basit bir rm -rf cache.baksunucu çöker, en basit HTTP yanıtı bile rm çalışırken 16 saniye sürer, bu yüzden bunu yapamam.

Denedim ionice -c3 rm -rf cache.bakama işe yaramadı. Sunucunun SSD'si değil HDD'si var, muhtemelen SSD'de bu sorun olmayabilir.

En iyi çözümün nginx'in önbellek yöneticisinde yaptığı gibi bir tür kısma olacağına inanıyorum.

Bunu nasıl çözersiniz? Tam olarak bunu yapabilen herhangi bir araç var mı?

Ubuntu 16.04 üzerinde ext4


1
"Rm -rf cache.bak" dosyasından nasıl kurtardın? Yeniden adlandırmayı yaptığınızda nginx çalışıyor gibi görünüyor, bu nedenle dosya tanımlayıcılarını korumuş ve hatta yeni dizine geçmiş olabilir. Nginx'i tamamen kapatmanız, önbelleği silmeniz ve ardından yeniden başlatmanız gerektiğini düşünüyorum.
Jan Steinman

6
Gelecekte, lütfen önbelleğinizi ayrı bir dosya sistemine yapıştırın. Bu şekilde, milyonlarca dosyayı silmeye çalışmaktan çok daha hızlı olan bu dosya sistemini tıklatabilirsiniz. Birkaç yıl önce, milyonlarca dosya içeren bir hylafax biriktirme dizini ile bunu zor yoldan öğrendim.
Dennis Kaarsemaker

Nicerm kullanarak koşmaya çalıştın mı ?
Vladislav Rastrusny

Hızlı silmek için rsync'i deneyin - benzer bir vakanın yanıtları - unix.stackexchange.com/questions/37329/…
kawu

Tüm yorumlarınız için teşekkürler, bulguları yazma cevabına özetledim.
hyperknot

Yanıtlar:


9

Bunun gibi bir bash betiği oluşturun:

#!/bin/bash
rm -- "$*"
sleep 0.5

deleter.shÖrneğin adıyla kaydedin . Run chmod u+x deleter.shçalıştırılabilir hale getirmeniz.

Bu komut dosyası, kendisine iletilen tüm dosyaları bağımsız değişken olarak siler ve ardından 0,5 saniye uyur.

Sonra koşabilirsin

find cache.bak -print0 | xargs -0 -n 5 deleter.sh

Bu komut cache.bak dosyasındaki tüm dosyaların listesini alır ve aynı anda beş dosya adını silme komut dosyasına geçirir.

Böylece, bir kerede kaç dosyanın silineceğini ve her silme işlemi arasında ne kadar gecikmenin olacağını ayarlayabilirsiniz.


Bu çözüm için teşekkürler, genel yazıma ekledim. Ancak bir soru, bu büyük ns nasıl ele? Genellikle hata veren büyük dizinlerde * karakteriyle ilgili sorunlar yaşadım, durum böyle değil mi?
hyperknot

xargsbir komut satırının maksimum boyutunu anlar ve varsayılan olarak aşmamak için çalışır. Bu, bir seferde 5 yoldan fazla olmayan ek sınırlara sahiptir.
BowlOfRed

1
Sadece saniyede 10 dosya hızında 2 milyon dosyayı silmenin 55 saat süreceğini unutmayın.
Andrew Henle

4

Önbelleğinizi, yorumlarda belirtildiği gibi bağlayabileceğiniz / çıkarabileceğiniz ayrı bir dosya sistemine kaydetmeyi düşünmelisiniz. Siz bulana kadar, /usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -deleteikili bul / / usr / bin altında yer aldığını ve ilerlemeyi ekranda görmek istediğinizi varsayarak bu tek astarı kullanabilirsiniz . Uykunuzu buna göre ayarlayın, böylece HDD'nizi aşırı zorlamayın.


-print0Burada hiçbir şeye ihtiyaç duymazsınız, çünkü findhiçbir yerde üretim yapmazsınız.
Tero Kilkanen

Rm-ing ile ilgileniyor olabilirsiniz. Paranoia deyin, ama her zaman doğru dosyaları sildiğimden emin olmak istiyorum.
Alex

Ah doğru, komutu doğru çözmedim, kötüyüm.
Tero Kilkanen

3

Bir find komutunun çıktısını tüketen bir komut dosyasında ionice denemek isteyebilirsiniz. Aşağıdaki gibi bir şey:

ionice -c3 $(
for file in find cache.bak -type f; do
    rm $file
done
for dir in find cache.bak -depthe -type d -empty; do
    rmdir $dir
done
)

Dosya sistemine bağlı olarak, her dosya silme dizinin tamamını yeniden yazmanıza neden olabilir. Büyük dizinler için bu bir hit olabilir. İnode tablosunda gerekli ek güncellemeler ve muhtemelen boş bir alan listesi vardır.

Dosya sisteminde bir günlük varsa, değişiklikler dergiye yazılır; uygulamalı; ve dergiden çıkarıldı. Bu yazma yoğun aktivite için G / Ç gereksinimlerini artırır.

Önbellek için günlük içermeyen bir dosya sistemi kullanmak isteyebilirsiniz.

İyonice yerine, eylemleri sınırlamak için bir uyku komutu kullanabilirsiniz. Bu, iyonice olmasa bile çalışacaktır, ancak tüm dosyalarınızı silmeniz uzun zaman alacaktır.


2

Burada hem sonucumu hem de çözümümü göstermek istediğim birçok yararlı cevap / yorum aldım.

  1. Evet, böyle bir şeyin olmasını önlemenin en iyi yolu , önbellek dizinini ayrı bir dosya sisteminde tutmaktır. Bir dosya sistemini nuking / hızlı biçimlendirmek, üzerinde kaç dosya / dizin bulunduğuna bağlı olmaksızın, her zaman en fazla birkaç saniye (belki dakika) alır.

  2. ionice/ niceSilme işlemi aslında neredeyse hiç G / Ç neden çünkü çözümleri, hiçbir şey yapmadı. G / Ç'ye neden olan şey, dosyaların silme işlemi tarafından çok hızlı bir şekilde silindiği zaman çekirdek / dosya sistemi düzey kuyruklarının / arabelleklerinin dolduğuna inanmaktı.

  3. Çözme şeklim Tero Kilkanen'in çözümüne benziyor, ancak bir kabuk betiği çağırmayı gerektirmiyordu. Silme --bwlimithızını sınırlamak için rsync'in yerleşik anahtarını kullandım.

Tam komut şuydu:

mkdir empty_dir
rsync -v -a --delete --bwlimit=1 empty_dir/ cache.bak/

Şimdi bwlimit, bant genişliğini kilobayt olarak belirtir, bu durumda dosyaların dosya adına veya yoluna uygulanır. 1 KBps olarak ayarlandığında, saatte yaklaşık 100.000 veya saniyede 27 dosya siliniyordu. Dosyalar cache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1e47 karakter uzunluğunda göreli yollara sahipti , bu yüzden saniyede 1000/47 ~ = 21 dosya verecekti, bu yüzden saatte 100.000 dosya tahminime benzer.

Şimdi neden --bwlimit=1? Çeşitli değerleri denedim:

  • 10000, 1000, 100 -> sistem eskisi gibi yavaşlıyor
  • 10 -> sistem bir süre oldukça iyi çalışıyor, ancak dakikada bir kez kısmi yavaşlamalara neden oluyor. HTTP yanıt süreleri hala <1 sn.
  • 1 -> hiç sistem yavaşlaması yok. Acelem yok ve bu şekilde <1 günde 2 milyon dosya silinebilir, bu yüzden seçiyorum.

Ben rsync yerleşik yöntem basitliğini seviyorum, ama bu çözüm göreli yolun uzunluğuna bağlıdır. Çoğu insan deneme yanılma yoluyla doğru değeri bulacağından büyük bir sorun değil.


Ve şimdi "mv cache.dir-old / dev / null" gibi bir şey yaptıysanız disk efektinin ne olacağını merak ediyorum
ivanivan
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.