Cara menghapus jutaan file tanpa mengganggu server

11

Saya ingin menghapus direktori cache nginx, yang saya hapus dengan cepat:

mv cache cache.bak
mkdir cache
service nginx restart

Sekarang saya punya cache.bakfolder yang memiliki 2 juta file. Saya ingin menghapusnya, tanpa mengganggu server.

Sederhana rm -rf cache.bakmembuang server, bahkan respons HTTP paling sederhana membutuhkan 16 detik saat rm berjalan, jadi saya tidak bisa melakukan itu.

Saya mencoba ionice -c3 rm -rf cache.bak, tetapi itu tidak membantu. Server memiliki HDD, bukan SSD, mungkin pada SSD ini mungkin tidak menjadi masalah.

Saya percaya solusi terbaik akan menjadi semacam pelambatan, seperti bagaimana built-in cache manager nginx.

Bagaimana Anda menyelesaikan ini? Apakah ada alat yang bisa melakukan ini?

ext4 di Ubuntu 16.04

hyperknot
sumber
1
Bagaimana Anda memulihkan dari "rm -rf cache.bak"? Tampaknya nginx sedang berjalan ketika Anda mengganti nama, sehingga mungkin mempertahankan deskriptor file dan bahkan beralih ke direktori baru. Saya pikir Anda perlu mematikan nginx sepenuhnya, menghapus cache, lalu memulai kembali.
Jan Steinman
6
Di masa depan, harap tempelkan cache Anda di sistem file yang terpisah. Dengan begitu Anda dapat dengan mudah mem-sistem file itu, yang jauh lebih cepat daripada mencoba menghapus jutaan file. Belajar ini dengan cara yang sulit beberapa tahun yang lalu dengan direktori spool hylafax yang berisi zillions file.
Dennis Kaarsemaker
Sudahkah Anda mencoba menjalankan rmmenggunakan nice ?
Vladislav Rastrusny
Coba rsync untuk menghapus dengan cepat - jawaban untuk kasus serupa - unix.stackexchange.com/questions/37329/…
kawu
Terima kasih atas semua komentarnya, saya telah meringkas temuan saya untuk jawaban penulisan.
hyperknot

Jawaban:

9

Buat skrip bash seperti ini:

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

Simpan dengan nama deleter.shmisalnya. Jalankan chmod u+x deleter.shuntuk membuatnya dapat dieksekusi.

Script ini menghapus semua file yang dikirimkan sebagai argumen, dan kemudian tidur 0,5 detik.

Lalu, Anda bisa berlari

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

Perintah ini mengambil daftar semua file di cache.bak dan meneruskan lima nama file sekaligus ke skrip hapus.

Jadi, Anda dapat menyesuaikan berapa banyak file yang dihapus sekaligus, dan berapa lama penundaan antara setiap operasi penghapusan.

Tero Kilkanen
sumber
Terima kasih atas solusi ini, saya telah memasukkannya ke dalam keseluruhan luncuran saya. Namun satu pertanyaan, bagaimana ini menangani ns besar? Saya biasanya memiliki masalah dengan karakter * di direktori besar yang memberikan kesalahan, bukankah ini masalahnya?
hyperknot
xargsmemahami ukuran maksimum baris perintah dan mencoba untuk tidak melampauinya secara default. Yang satu ini memiliki batas tambahan tidak lebih dari 5 jalur sekaligus.
BowlOfRed
1
Perlu diketahui bahwa pada kecepatan 10 file per detik, akan dibutuhkan 55 jam untuk menghapus 2 juta file.
Andrew Henle
4

Anda harus mempertimbangkan untuk menyimpan cache Anda pada sistem file terpisah yang dapat Anda pasang / lepaskan dari akun seseorang yang dinyatakan dalam komentar. Sampai Anda melakukannya, Anda dapat menggunakan liner yang satu ini /usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -deletedengan asumsi biner find Anda berada di bawah / usr / bin dan Anda ingin melihat progresnya di layar. Sesuaikan tidur sesuai, sehingga Anda tidak terlalu menekankan HDD Anda.

Alex
sumber
Orang tidak perlu di -print0sini, karena Anda tidak menyalurkan output di findmana pun.
Tero Kilkanen
Anda mungkin hanya tertarik pada apa yang rm-ing. Sebut saja paranoia, tetapi saya selalu ingin memastikan saya menghapus file yang tepat.
Alex
Ah benar, saya tidak memecahkan kode perintah dengan benar, salah saya.
Tero Kilkanen,
3

Anda mungkin ingin mencoba ionice pada skrip yang menggunakan output dari perintah find. Sesuatu seperti yang berikut ini:

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
)

Bergantung pada sistem file, setiap penghapusan file dapat mengakibatkan penulisan ulang seluruh direktori itu. Untuk direktori besar yang bisa sangat sukses. Ada pembaruan tambahan yang diperlukan untuk tabel inode, dan mungkin daftar ruang kosong.

Jika sistem file memiliki jurnal, perubahan ditulis ke jurnal; terapan; dan dihapus dari jurnal. Ini meningkatkan persyaratan I / O untuk kegiatan intensif menulis.

Anda mungkin ingin menggunakan sistem file tanpa jurnal untuk cache.

Alih-alih ionice, Anda dapat menggunakan perintah tidur untuk menilai membatasi tindakan. Ini akan berfungsi bahkan jika ionice tidak, tetapi akan memakan waktu lama untuk menghapus semua file Anda.

BillThor
sumber
2

Saya mendapat banyak jawaban / komentar yang berguna di sini, yang ingin saya simpulkan sekaligus tunjukkan solusi saya juga.

  1. Ya, cara terbaik untuk mencegah hal seperti itu terjadi adalah dengan tetap menyimpan cache cache pada sistem file yang terpisah. Nuking / memformat cepat sistem file selalu membutuhkan waktu beberapa detik (mungkin beberapa menit) paling banyak, tidak terkait dengan berapa banyak file / dir yang ada di dalamnya.

  2. The ionice/ nicesolusi tidak melakukan apa-apa, karena proses menghapus sebenarnya disebabkan hampir tidak ada I / O. Apa yang menyebabkan I / O adalah saya yakin antrian / buffer level kernel / filesystem terisi ketika file dihapus terlalu cepat oleh proses hapus.

  3. Cara saya menyelesaikannya mirip dengan solusi Tero Kilkanen, tetapi tidak perlu memanggil skrip shell. Saya menggunakan rsync's built in --bwlimitswitch untuk membatasi kecepatan penghapusan.

Perintah penuh adalah:

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

Sekarang bwlimit menentukan bandwidth dalam kilobyes, yang dalam hal ini diterapkan pada nama file atau path file. Dengan mengatur ke 1 KBps, itu menghapus sekitar 100.000 file per jam, atau 27 file per detik. File memiliki jalur relatif seperti cache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1e, yang panjangnya 47 karakter, sehingga akan memberikan 1000/47 ~ = 21 file per detik, jadi agak mirip dengan tebakan saya 100.000 file per jam.

Sekarang kenapa --bwlimit=1? Saya mencoba berbagai nilai:

  • 10000, 1000, 100 -> sistem melambat seperti sebelumnya
  • 10 -> sistem bekerja cukup baik untuk sementara waktu, tetapi menghasilkan pelambatan parsial sekitar satu menit sekali. Waktu respons HTTP masih <1 detik.
  • 1 -> tidak ada perlambatan sistem sama sekali. Saya tidak terburu-buru dan 2 juta file dapat dihapus dalam <1 hari dengan cara ini, jadi saya memilihnya.

Saya suka kesederhanaan metode built in rsync, tetapi solusi ini tergantung pada panjang jalur relatif. Bukan masalah besar karena kebanyakan orang akan menemukan nilai yang tepat melalui coba-coba.

hyperknot
sumber
Dan sekarang saya ingin tahu apa efek disk jika Anda melakukan sesuatu seperti "mv cache.dir-old / dev / null"
ivanivan