Як видалити мільйони файлів, не турбуючи сервер


11

Я хотів би видалити каталог кешу nginx, який я швидко очистив:

mv cache cache.bak
mkdir cache
service nginx restart

Зараз у мене cache.bakпапка, яка містить 2 мільйони файлів. Я хотів би видалити його, не турбуючи сервер.

Простий rm -rf cache.bakкошик сервера, навіть найпростіший HTTP-відповідь займає 16 секунд під час роботи rm, тому я не можу цього зробити.

Я спробував ionice -c3 rm -rf cache.bak, але це не допомогло. На сервері є жорсткий диск, а не SSD, можливо, на SSD це може не бути проблемою.

Я вважаю, що найкращим рішенням було б якесь придушення, як, наприклад, як вбудований nginx в кеш-менеджер.

Як би ви вирішили це? Чи є інструмент, який може зробити саме це?

ext4 на Ubuntu 16.04


1
Як ви відновилися з "rm -rf cache.bak"? Здається, що nginx працював під час перейменування, тому він, можливо, підтримував дескриптори файлів і навіть перейшов на новий каталог. Я думаю, вам потрібно повністю вимкнути nginx, видалити кеш, а потім перезапустити.
Ян Штейнман

6
Надалі введіть кеш-пам'ять в окрему файлову систему. Таким чином ви можете просто запустити цю файлову систему, що набагато швидше, ніж намагатися видалити мільйони файлів. Навчився цьому важким способом кілька років тому, використовуючи каталог гілафакс-котушки, що містить мільйони файлів.
Денніс Каарсемейкер

Ви намагалися запустити, rmвикористовуючи приємне ?
Владислав Раструсний

Спробуйте rsync для швидкого видалення - відповіді на подібний випадок - unix.stackexchange.com/questions/37329/…
kawu

Дякую за всі коментарі, я підсумував свої висновки, щоб написати відповідь.
гіперкнот

Відповіді:


9

Зробіть сценарій bash таким чином:

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

Збережіть його, наприклад, з ім'ям deleter.sh. Запустіть, chmod u+x deleter.shщоб зробити його виконуваним.

Цей скрипт видаляє всі передані йому файли як аргументи, а потім спить 0,5 секунди.

Потім ви можете бігти

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

Ця команда отримує список усіх файлів у cache.bak і одночасно передає п'ять імен файлів до сценарію видалення.

Отже, ви можете налаштувати кількість файлів, які видаляються за один раз, і як тривала затримка між кожною операцією видалення.


Дякую за це рішення, я включив його до свого загального опису. Однак одне питання, як це поводження з великими росіянами? У мене зазвичай виникали проблеми з * символом у великих каталогах, що дають помилки, чи не так?
гіпернот

xargsрозуміє максимальний розмір командного рядка і намагається не перевищувати його за замовчуванням. У цього додаткового обмеження не більше 5 шляхів одночасно.
BowlOfRed

1
Просто пам’ятайте, що зі швидкістю 10 файлів в секунду знадобиться 55 годин, щоб видалити 2 мільйони файлів.
Ендрю Генле

4

Вам слід подумати про збереження кешу в окремій файловій системі, яку ви зможете змонтувати / відключити, як хтось вказав у коментарях. Поки ви не можете скористатися цим вкладишем, /usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -deleteприпустивши, що ваш двійковий файл знаходиться під / usr / bin, і ви хочете бачити хід на екрані. Відповідно налаштуйте сон, щоб не перенапружувати свій жорсткий диск.


Тут не потрібно -print0, оскільки ви не розміщуєте висновок findніде.
Tero Kilkanen

Вам просто може бути цікаво, що таке Rm-ing. Назвіть це параною, але я завжди хочу бути впевненим, що я видаляю потрібні файли.
Олексій

А правда, я не розшифрував команду правильно, моє погано.
Tero Kilkanen

3

Ви можете спробувати ionice на скрипті, що використовує висновок команди find. Щось таке:

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
)

Залежно від файлової системи кожне видалення файлу може призвести до перезапису всього цього каталогу. Для великих каталогів, які можуть бути досить хітом. До таблиці inode потрібні додаткові оновлення та, можливо, список вільного місця.

Якщо файлова система має журнал, зміни вносяться до журналу; застосовується; і вилучено з журналу. Це збільшує вимоги вводу / виводу для активної запису.

Ви можете використовувати файлову систему без журналу для кешу.

Замість ionice ви можете скористатися командою сну для обмеження дій. Це буде працювати, навіть якщо ionice цього не зробить, але для видалення всіх файлів знадобиться тривалий час.


2

Тут я отримав багато корисних відповідей / коментарів, які хотів би зробити висновок, а також показати своє рішення.

  1. Так, найкращий спосіб запобігти такій справі - це зберегти кеш-пам'ять в окремій файловій системі. Запуск / швидке форматування файлової системи завжди займає не більше декількох секунд (можливо, хвилин), не залежно від того, скільки файлів / режимів було на ній.

  2. Рішення ionice/ niceнічого не зробили, оскільки процес видалення насправді не спричинив майже жодного вводу / виводу. Причиною вводу / виводу було те, що я вважаю, що черги / буфери рівня ядра / файлової системи заповнюються, коли файли видаляються занадто швидко процесом видалення.

  3. Те, як я вирішив це, схоже на рішення Теро Кілканена, але не вимагає виклику сценарію оболонки. Я використовував вбудований --bwlimitперемикач rsync, щоб обмежити швидкість видалення.

Повна команда була:

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

Тепер bwlimit вказує пропускну здатність у кілобаях, яка в цьому випадку застосовується до імені файлу або шляху до файлів. Встановивши його в 1 Кбіт / с, він видаляв близько 100 000 файлів на годину або 27 файлів в секунду. Файли мали відносні шляхи на зразок cache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1e, який становить 47 символів, тож він давав би 1000/47 ~ = 21 файл в секунду, настільки схожий на мою здогадку, що 100 000 файлів на годину.

Тепер чому --bwlimit=1? Я спробував різні значення:

  • 10000, 1000, 100 -> уповільнення системи, як і раніше
  • 10 -> система працює досить добре деякий час, але створює часткові уповільнення раз на хвилину або близько того. Часи відповіді HTTP ще <1 сек.
  • 1 -> відсутність уповільнення роботи системи взагалі. Я не поспішаю, і 2 мільйони файлів можна видалити за <1 день таким чином, тому я вибираю його.

Мені подобається простота вбудованого методу rsync, але це рішення залежить від відносної довжини шляху. Не велика проблема, оскільки більшість людей знайдуть правильне значення шляхом спроб та помилок.


І тепер мені цікаво, який би був ефект диска, якби ви зробили щось на кшталт "mv cache.dir-old / dev / null"
ivanivan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.