Я генерирую более 50 ГБ файлов кеша на моем сервере RHEL (а типичный размер файла составляет 200 КБ, поэтому файлы огромны). Когда я пытаюсь удалить эти файлы, это занимает 8-10 часов.
Однако более серьезная проблема заключается в том, что в течение этих 8-10 часов загрузка системы становится критической. Есть ли способ держать нагрузку системы под контролем во время удаления?
Я пробовал использовать
nice -n19 rm -rf *
но это не помогает в загрузке системы.
P.S. Я задал тот же вопрос о superuser.com но не получил достаточно хорошего ответа, поэтому пытаюсь здесь.
Вот некоторые ориентиры для различных операций и файловых систем для справки. (Конечно, в загруженной системе у вас будут другие результаты, но, надеюсь, это даст вам представление о том, чего ожидать).
Если бы я был в вашем кресле, я бы попытался получить базовую оценку сценария:
Некоторые цифры.
На тетради 5-летней давности ext3 смонтированный rw, noatime, running top и больше ничего, создайте 10k каталогов с помощью сценария оболочки create10kdirs.sh
#!/bin/bash
for i in $(seq 10000)
do
mkdir $i
done
sudo time ./create10kdirs.sh
24.59 пользователь
20.70система
0: 47.04 прошло
96% ЦП (0avgtext + 0avgdata 0maxresident) k80inputs + 8outputs (1major + 2735150minor) pagefaults 0swaps
удалить 10k каталогов с помощью sudo time rm -rf
0.10 пользователь
19,75система
0: 20.71 прошло
95% ЦП (0avgtext + 0avgdata 0maxresident) k0inputs + 8outputs (0major + 222minor) pagefaults 0swaps
такое же оборудование, ext4 смонтированный rw, noatime создать 10k каталогов с помощью сценария оболочки sudo time create10kdirs.sh
23.96 пользователь
22.31система
0: 49.26 прошло
93% CPU (0avgtext + 0avgdata0maxresident) k1896inputs + 8outputs (20major + 2715174minor) pagefaults 0swaps
удалить 10k каталогов с помощью sudo time rm -rf
0,13 пользователь
16.96система
0: 28.21 прошло
60% ЦП (0avgtext + 0avgdata0maxresident) k10160inputs + 0outputs (1major + 219minor) pagefaults0swaps
Тетрадь 4-х летней давности, xfs установленный rw, relatime, nobarrier на USB sudo time create10kdirs.sh
14.19 пользователь
13.86система
0: 29.75 прошло
94% ЦП (0avgtext + 0avgdata0maxresident) k432inputs + 0outputs (1major + 2735243minor) pagefaults 0swaps
удалить 10k каталогов с помощью
sudo time rm -rf
0,13 пользователь
2.65система
0: 08.20 прошло
33% ЦП (0avgtext + 0avgdata 0maxresident) k120inputs + 0outputs (1major + 222minor) pagefaults 0swaps
Вывод: это старое оборудование стирает 400 тыс. Маленьких файлов + папок на ext3 примерно за 21 с * 40 = 12 мин 40 с. На xfs (без барьеров) это будет примерно за 5 мин. 20 сек. Конечно, в обоих случаях тестовая машина не находилась под большой нагрузкой, но мне кажется, что ваши проблемы не связаны строго с вашим выбором файловой системы.
EDIT2 Кроме того, после выполнения вышеуказанных тестов я пошел попробовать удалить с помощью find. -mindepth 1 -maxdepth 1 -delete
и результаты !:
ext3 удаляет 10k каталогов с помощью sudo time find. -mindepth 1 -maxdepth 1 -delete
0,04 пользователя
0.44система
0: 00.88прошло
55% ЦП (0avgtext + 0avgdata 0maxresident) k516inputs + 8outputs (1major + 688minor) pagefaults0swaps
ext4 удалить 10k каталогов с помощью
sudo time find. -mindepth 1 -maxdepth 1 -delete
0,05 пользователя
0.66система
0: 01.02 прошло
70% ЦП (0avgtext + 0avgdata 0maxresident) k568inputs + 0outputs (1major + 689minor) подкачки страниц
xfs удаляет 10k каталогов с помощью
sudo time find. -mindepth 1 -maxdepth 1 -delete
0,06 пользователя
0.84система
0: 04.55 прошло
19% ЦП (0avgtext + 0avgdata 0maxresident) k416inputs + 0outputs (3major + 685minor) pagefaults 0swaps
Реальный вывод заключается в том, что rm -rf не очень умен и неэффективен для больших деревьев. (при условии, что мой тестовый пример действительно репрезентативен).
Примечание: я также тестировал вариант xargs, он быстрый, но не такой быстрый, как указано выше.
Как вы упомянули в комментарии, вы используете ext3
.
Хорошо известно, что rm
производительность для больших файлов на ext3 оставляет желать лучшего; это одна из вещей, которые были зафиксированы в ext4
. См. Например эта почта, или ядро новички (где упоминается, что экстенты улучшают скорость удаления и усечения для больших файлов).
Я не знаю, насколько это применимо к вашим типичным размерам файлов. Я бы ожидал, что это применится хотя бы немного, так как примерно с 200 КБ вы уже будете использовать косвенные блоки на ext3
, по сравнению, возможно, с одним экстентом на ext4
.
В качестве обходного пути (поскольку вы, вероятно, не перейдете на ext4
только для этого), каждый раз удаляйте только несколько файлов и добавляйте sleep
между удалениями. Это некрасиво, но должно помочь снизить нагрузку.
Кроме того, если потеря файлов при отключении питания не является проблемой (поскольку это какой-то кеш), вы можете поместить их в отдельный раздел, который вы mkfs
снова при загрузке и используйте ext3
без журнала или даже ext2
. Причиной высокой нагрузки, вероятно, является сбрасывание журнала на диск, конфликтующий с чтениями (вы упомянули в другом сообщении, что у вас много одновременных чтений).
Возможно оболочка является причиной проблемы. Вы должны использовать прямой поиск: find /dir -mindepth 1 -maxdepth 1 -delete
Это может быть связано, а может и не быть, но у меня были случаи, когда rm
не мог обработать количество файлов, которые я предоставил ему в командной строке (через оператор звездочки). Вместо этого я бы использовал следующую команду из оболочки:
for i in *; do rm -rf $i; done
В этом случае вы можете удалять деревья, и в этом случае вышеуказанное может не дать того, что вам нужно. Возможно, вам придется разделить операцию удаления на части, например
for i in [a-mA-M]*; do rm -rf $i; done
for i in [n-zN-Z]*; do rm -rf $i; done
Это всего лишь 250 000 файлов или около того, на самом деле не должно быть проблемой - какую файловую систему вы используете и используется ли этот том для чего-нибудь еще?
Когда у вас много файлов, как вы описали, вы каждый раз вызываете команду. Также вы должны иметь в виду, что в журналируемой FS вы имеете дело с попаданиями в буфер и метаданными, которые могут сильно повлиять на время процесса.
Лучше всего использовать команду find, как упомянуто выше, только с менее очевидной функцией.
find / -name filename.* -exec /bin/rm -f '{}' \+
В основном "+" - ваш друг. Это создает имена файлов в наборах и вызывает команду rm один раз для каждого набора. Это почти то же самое, что и xargs, но вам не нужно беспокоиться о правильных флагах, если вы используете BSD / Linux.
Очень любопытно, насколько это ускоряет для вас. Так что ответьте, если вы все еще здесь. Удачи !
Изучив тесты файловой системы, я выбрал JFS в качестве хранилища файлов для моих видеофайлов Mythtv, потому что файлы удаляются быстро (а мифы ожидают завершения удаления, что замедляет ввод-вывод).
Вы также можете вызвать rm через find и xargs вместо rm -rf. Это могло быть быстрее:
find <dir> | xargs rm
Как насчет того, чтобы передать список этих файлов Perl и использовать его функцию unlink?
find <dir> | perl -nle 'unlink;'
Я согласен, что это не займет так много времени, но в зависимости от используемого базового хранилища этого можно ожидать при интенсивном чтении. Я думаю, что в конечном итоге ваше лучшее решение - добавить дополнительные диски и разделить вашу деятельность между ними. RAID может помочь в некоторых сценариях, если вы пойдете по этому пути. Что говорит вам iostat в это время? Вы также можете использовать цикл for и заключить команды 'rm' во 'time', чтобы получить дополнительную информацию.
Другая возможность, конечно, в зависимости от вашей настройки и приложения, но, может быть, вы могли бы сделать эти файлы кеша в другом разделе и просто периодически форматировать диск, а не удалять файлы? Я думаю, что запуск mkfs значительно сократит время, но ваше приложение будет недоступно, пока это произойдет, поэтому оно не будет идеальным.
Мне также нравится идея почаще их убирать. Скажем, в cron вы планируете что-то вроде этого каждый час:
find ./ -maxdepth 1 -type f -name "some pattern" -ctime +1 -exec rm -f {} \;
Это приведет к удалению всех файлов старше 24 часов, вместо того, чтобы пытаться сделать их все сразу.