Как удалить миллионы файлов, не мешая серверу

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

hyperknot
источник
1
Как вы оправились от "rm -rf cache.bak"? Похоже, что nginx работал, когда вы делали переименование, поэтому он мог поддерживать файловые дескрипторы и даже переключаться в новый каталог. Я думаю, что вам нужно полностью закрыть nginx, удалить кеш, затем перезапустить.
Ян Стейнман
6
В будущем, пожалуйста, поместите ваш кеш в отдельную файловую систему. Таким образом, вы можете просто уничтожить эту файловую систему, что гораздо быстрее, чем пытаться удалить миллионы файлов. Несколько лет назад это усердно изучалось с помощью каталога каталогов Hylafax, содержащего миллионы файлов.
Деннис Каарсемакер
Вы пытались бежать, rmиспользуя хороший ?
Владислав Раструсный
Попробуйте rsync для быстрого удаления - ответы на аналогичный случай - unix.stackexchange.com/questions/37329/…
kawu
Спасибо за все комментарии, я резюмировал свои выводы, чтобы написать ответ.
hyperknot

Ответы:

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 и передает пять имен файлов за раз в сценарий удаления.

Таким образом, вы можете настроить количество файлов, удаляемых за раз, и сколько времени задерживается между каждой операцией удаления.

Теро Килканен
источник
Спасибо за это решение, я включил его в мою общую рецензию. Один вопрос, однако, как это обрабатывает большие нс? У меня обычно были проблемы с символом * в больших каталогах, что приводило к ошибкам, не правда ли?
hyperknot
xargsпонимает максимальный размер командной строки и старается не превышать его по умолчанию. Этот имеет дополнительные ограничения не более 5 путей одновременно.
BowlOfRed
1
Имейте в виду, что при скорости 10 файлов в секунду удаление 2 миллионов файлов займет 55 часов.
Эндрю Хенле
4

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

Alex
источник
Здесь это не нужно -print0, поскольку вы нигде не обмениваетесь информацией find.
Теро Килканен
Вы просто можете быть заинтересованы в том, что происходит. Назовите это паранойей, но я всегда хочу быть уверенным, что удаляю нужные файлы.
Алекс
Ах да, я не правильно расшифровал команду, мой плохой.
Теро Килканен
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 вы можете использовать команду sleep для ограничения скорости действий. Это будет работать, даже если ionice нет, но для удаления всех ваших файлов потребуется много времени.

BillThor
источник
2

Здесь я получил много полезных ответов / комментариев, которые я хотел бы завершить, а также показать свое решение.

  1. Да, лучший способ предотвратить это - сохранить каталог кеша в отдельной файловой системе. Быстрое форматирование файловой системы всегда занимает не более нескольких секунд (возможно, минут), независимо от того, сколько на ней файлов / каталогов.

  2. В ionice/ niceрешения не было ничего не делать, потому что процесс удаления на самом деле причиной практически нет I / O. Что вызвало ввод / вывод, я полагаю, что очереди / буферы на уровне ядра / файловой системы заполнялись, когда файлы были удалены слишком быстро процессом удаления.

  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, но это решение зависит от длины относительного пути. Не большая проблема, так как большинство людей нашли бы правильное значение методом проб и ошибок.

hyperknot
источник
И теперь мне любопытно, что будет с эффектом диска, если вы сделаете что-то вроде «mv cache.dir-old / dev / null»
ivanivan