Удаление миллионов файлов

38

У меня был каталог, заполненный миллионами изображений в формате gif. Слишком много для команды rm.

Я пытался найти команду поиска следующим образом:

find . -name "*.gif" -print0 | xargs -0 rm

Проблема в том, что он очень сильно тормозит мою машину и вызывает тайм-ауты для клиентов, так как это сервер.

Есть ли способ быстрее удалить все эти файлы ... без блокировки машины?

Corepuncher
источник
У меня скорость удаления около 6 ГБ / ч с помощью команды «хороший поиск», приведенной ниже. Вероятно, потребуется 48 часов, чтобы избавиться от всех файлов. Причина, по которой это произошло, была неудачной. «горизонт событий» с помощью команды rm, затем он убежал.
3
Разве удаление всего каталога не будет существенно быстрее? Просто достаньте «хорошие» файлы, прежде чем уничтожать оставшиеся…
tucuxi
Ну, каждый файл сейчас плохой, потому что он был перемещен в / dir_old, а я переделал / dir. Но не будет ли у rmdir такое же ограничение, как у rm *?
@Corepuncher: Я ожидал бы, что удаление всего каталога (как с, rm -rfбыло бы быстрее. Это стоит попробовать.
Jason R
В настоящее время я запускаю "rm -rf" в директории. Он работает уже более 20 минут ... пока нет изменений в размере диска. Но также он также автоматически не возвращал «список аргументов слишком длинный». Единственная проблема в том, что это действительно забивает мою машину и заставляет другие вещи замедляться / терпеть неудачу. Не уверен, как долго отпустить.

Ответы:

44

Быстрее не обязательно то, что вы хотите. Возможно, вы захотите работать медленнее , поэтому удаление во время работы отнимает меньше ресурсов.

Используйте nice (1), чтобы понизить приоритет команды.

nice find . -name "*.gif" -delete

Для процессов ввода-вывода nice (1) может быть недостаточно. Планировщик Linux принимает во внимание ввод / вывод, а не только процессор, но вам может потребоваться более точное управление приоритетом ввода / вывода.

ionice -c 2 -n 7 find . -name "*.gif" -delete

Если этого не произойдет, вы также можете добавить сон, чтобы действительно замедлить его.

find . -name "*.gif" -exec sleep 0.01 \; -delete
Джон Кугельман поддерживает Монику
источник
3
вау ... миллионы файлов со сном .1 с ... нужен день для 864000 файлов.
glglgl
7
@glglgl Хорошо, умница. Я изменил время ожидания. :-P
Джон Кугельман поддерживает Монику
28
Сон может быть хорошим выбором, но хороший не подойдет, так как задача здесь связана с вводом-выводом, а не с процессором; вместо этого вы можете попробовать ionice. Обратите внимание, что если сон будет слишком маленьким, он будет бесполезен.
Matteo Italia
3
@glglgl: дело в том, что если вы не хотите вызывать сбои в работе сервера, вам нужно идти медленно, время, когда этот код неактивен, позволяет серверу действительно выполнять полезную работу с диском.
Matteo Italia
1
+1 за sleepдобавление - у меня были проблемы с серверами, задыхающимися от ввода-вывода, несмотря на использование ionice -c 3. Это значительно увеличивает время, необходимое для очистки файлов (конечно), но я предпочел бы подождать, чем закрыть приложение ...
Ола Тувессон,
22

Поскольку вы работаете в Linux, и эта задача, вероятно, связана с вводом / выводом, я советую дать вашей команде приоритет планировщика ввода / вывода, используя ionice(1):

ionice -c3 find . -name '*.gif' -delete

По сравнению с вашей исходной командой, я полагаю, что это может сэкономить еще несколько циклов ЦП, если не использовать канал xargs.


источник
@Braiam Что ты имеешь в виду? Это не то, find ... -execгде это имело бы смысл.
О да, прости. Виноват. Ты уверен, что это эффективно, правда?
Брайам
1
Ну, find(1)документация утверждает, что так. :) И должно быть очевидно, что findудаление файлов само по себе более эффективно, чем создание rmкоманды для этого.
1
Я попробовал несколько предложенных версий в папке с 4 миллионами файлов на рабочем сервере, и это единственная версия, которая не душит систему. ionice -c3понижает prio, чтобы просто бежать, когда IO бездействует иначе, так что это идеально. Обратите внимание, что, поскольку -deleteэто не является стандартным для поиска, вы можете сделать то же самое (включая обратную связь, что он работает), используя эту команду: ionice -c 3 find . -name '*.gif' -exec echo {} \; -exec rm {} \;- Медленный, но без iowaits важных процессов.
Кристофер Лёркен
13

Нет.

Нет более быстрого способа, приложения из soft-формата диска. Файлы передаются rm сразу (до предела командной строки, его также можно установить в xargs), что намного лучше, чем вызывать rm для каждого файла. Так что нет, определенно нет более быстрого пути.

Использование nice(или reniceна работающем процессе) помогает только частично, потому что это для планирования ресурсов процессора , а не диска! И использование процессора будет очень низким. Это слабое место в Linux - если один процесс «съедает» диск (т.е. много работает с ним), вся машина зависает. Модифицированное ядро ​​для использования в реальном времени может быть решением.

На сервере я бы позволил другим процессам выполнять свою работу вручную, включая паузы, чтобы сервер "дышал":

find . -name "*.gif" > files
split -l 100 files files.
for F in files.* do
    cat $F | xargs rm
    sleep 5 
done

Это будет ждать 5 секунд после каждых 100 файлов. Это займет гораздо больше времени, но ваши клиенты не должны замечать каких-либо задержек.

Tomas
источник
«Файлы передаются в rm сразу (до предела командной строки»), поэтому, когда оболочка получает команду rm *, она расширяется *в строку со всеми именами файлов и передает ее rm? Это невероятно глупо. Зачем оболочки расширить подстановочные знаки?
:-D @Joker_vD, ты шутишь, как подсказывает твое имя? :-)
Томас
2
@Joker_vD: совместимость с решением Unix 1970 года или около того. Windows не делает этого. Там программы могут передавать групповые символы в FindNextFile / FindNextFile, поэтому они получают результаты по одному.
MSalters
@ Томас Не в этом случае. Честно говоря, я сразу вижу 2 проблемы с таким дизайном: во-первых, командная строка не резиновая; во-вторых, программа не может определить, была ли она вызвана с помощью *или, /*и поставить под сомнение такое решение пользователя.
1
@Joker_vD Есть много хороших вещей в оболочке, делающей подстановочные знаки. Это отличается от Windows, но не спешите с выводом, что это невероятно глупо только потому, что оно отличается от того, к чему вы привыкли. Если вы хотите узнать больше, я советую вам зайти в Google или разместить вопрос на соответствующем сайте Stack Exchange. Это огромная крушение для этой области комментариев.
Джон Кугельман поддерживает Монику
5

Если количество файлов, которые должны быть удалены, значительно превосходит число оставленных файлов, возможно, не самый эффективный подход - пройтись по дереву удаляемых файлов и выполнить все эти обновления файловой системы. (Это аналогично выполнению неуклюжего управления памятью с подсчетом ссылок, посещению каждого объекта в большом дереве, чтобы отбросить ссылку, вместо того, чтобы за один шаг превратить все ненужное в мусор, а затем просмотр всего, что доступно для очистки.)

То есть клонировать части дерева, которые должны быть сохранены, в другой том. Пересоздайте новую чистую файловую систему на исходном томе. Скопируйте сохраненные файлы обратно в их исходные пути. Это примерно похоже на копирование сборки мусора .

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

Это может быть непрактично в вашей системе и ситуации, но легко представить очевидные случаи, когда это путь.

Например, предположим, что вы хотите удалить все файлы в файловой системе. Какой смысл повторять и удалять по одному? Просто размонтируйте его и выполните «mkfs» поверх раздела, чтобы создать пустую файловую систему.

Или предположим, что вы хотите удалить все файлы, кроме полдюжины важных? Получите полдюжины оттуда и ... "mkfs" поверх.

В конце концов, существует определенная точка безубыточности, когда остается достаточно файлов, и рекурсивное удаление становится дешевле, принимая во внимание другие затраты, такие как время простоя.

Kaz
источник
4

Ты пытался:

find . -name "*.gif" -exec rm {} +

Знак + в конце заставит find включить больше файлов для выполнения одной команды rm. Проверьте этот вопрос для более подробной информации.

Бартош Фирин
источник
Это выполняется намного быстрее, чем -print0 | Решение xargs, потому что процесс rm вызывается не для каждого файла, а для большого их набора, и поэтому он вызывает меньшую нагрузку.
@JohnKugelman Вы правы, но это расширение GNU, которое не всегда доступно с помощью встроенной команды поиска .
CodeGnome
Хорошо, интересно, но это совершенно новая вещь (и -delete), которая не всегда должна быть там ...
Томас
Однако это, безусловно, не приносит ничего лучшего по сравнению с решением ОП.
Томас