Latar belakang: server fisik, sekitar dua tahun, drive SATA 7200-RPM terhubung ke kartu RAID 3Ware, noatime yang dipasang di ext3 FS dan data = dipesan, bukan di bawah beban gila, kernel 2.6.18-92.1.22.el5, uptime 545 hari . Direktori tidak mengandung subdirektori, hanya jutaan file kecil (~ 100 byte), dengan beberapa yang lebih besar (beberapa KB).
Kami memiliki server yang sudah agak cuckoo selama beberapa bulan terakhir, tetapi kami baru menyadarinya pada hari lain ketika server mulai tidak dapat menulis ke direktori karena mengandung terlalu banyak file. Secara khusus, itu mulai melempar kesalahan ini di / var / log / messages:
ext3_dx_add_entry: Directory index full!
Disk yang dimaksud memiliki banyak inode yang tersisa:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
Jadi saya menduga itu berarti kita mencapai batas berapa banyak entri dapat di file direktori itu sendiri. Tidak tahu berapa banyak file yang akan, tetapi tidak bisa lebih, seperti yang Anda lihat, lebih dari tiga juta. Bukan itu bagus, ingatlah! Tapi itu bagian pertama dari pertanyaan saya: persis apa batas atas itu? Apakah bisa merdu? Sebelum saya dimarahi - saya ingin meremehkannya ; direktori besar ini menyebabkan segala macam masalah.
Bagaimanapun, kami melacak masalah dalam kode yang menghasilkan semua file itu, dan kami telah memperbaikinya. Sekarang saya terjebak dengan menghapus direktori.
Beberapa opsi di sini:
rm -rf (dir)
Saya mencoba ini dulu. Saya menyerah dan membunuhnya setelah berjalan selama satu setengah hari tanpa dampak yang jelas.
- batalkan tautan (2) pada direktori: Pasti layak dipertimbangkan, tetapi pertanyaannya adalah apakah akan lebih cepat untuk menghapus file di dalam direktori melalui fsck daripada menghapus melalui batalkan tautan (2). Artinya, dengan satu atau lain cara, saya harus menandai inode tersebut sebagai tidak terpakai. Ini mengasumsikan, tentu saja, bahwa saya dapat memberitahu fsck untuk tidak menjatuhkan entri ke file in / lost + found; jika tidak, saya baru saja memindahkan masalah saya. Selain semua kekhawatiran lain, setelah membaca tentang ini sedikit lebih banyak, ternyata saya mungkin harus memanggil beberapa fungsi FS internal, karena tidak ada varian unlink (2) yang dapat saya temukan yang akan memungkinkan saya untuk menghapus dengan blithely direktori dengan entri di dalamnya. Pooh.
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
Ini sebenarnya adalah versi singkat; yang sebenarnya saya jalankan, yang hanya menambahkan beberapa pelaporan kemajuan dan berhenti bersih ketika kita kehabisan file untuk dihapus, adalah:
ekspor i = 0; waktu (sementara [benar]; lakukan ls -Uf | kepala -n 3 | grep -qF '.png' || istirahat; ls -Uf | kepala -n 10000 | xargs rm -f 2> / dev / null; ekspor i = $ (($ i + 10000)); gema "$ i ..."; Selesai )
Ini sepertinya bekerja dengan baik. Saat saya menulis ini, ia telah menghapus 260.000 file dalam sekitar tiga puluh menit terakhir.
- Seperti disebutkan di atas, apakah batas entri per-direktori dapat diatur?
- Mengapa diperlukan "real 7m9.561s / pengguna 0m0.001s / sys 0m0.001s" untuk menghapus satu file yang merupakan yang pertama dalam daftar yang dikembalikan oleh
ls -U
, dan mungkin butuh sepuluh menit untuk menghapus 10.000 entri pertama dengan perintah di # 3, tapi sekarang sudah cukup senang? Untuk itu, itu dihapus 260.000 dalam waktu sekitar tiga puluh menit, tetapi sekarang butuh lima belas menit lagi untuk menghapus 60.000 lebih. Mengapa ayunan besar dalam kecepatan? - Apakah ada cara yang lebih baik untuk melakukan hal semacam ini? Tidak menyimpan jutaan file dalam direktori; Saya tahu itu konyol, dan itu tidak akan terjadi pada jam tangan saya. Menelusuri masalah dan melihat melalui SF dan SO menawarkan banyak variasi
find
yang tidak akan secara signifikan lebih cepat daripada pendekatan saya karena beberapa alasan yang jelas. Tapi apakah ide delete-via-fsck punya kaki? Atau sesuatu yang lain sama sekali? Saya ingin sekali mendengar pemikiran out-of-the-box (atau di dalam-tidak-terkenal).
Output skrip akhir !:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
Jadi, tiga juta file dihapus dalam waktu lebih dari empat jam.
rm -rfv | pv -l >/dev/null
. pv harus tersedia di repositori EPEL .