Как стать автором
Обновить

Комментарии 103

мгновенное создание 200G
dd if=/dev/zero of=./disk-image bs=1M count=0 seek=200G
Только bs дожен быть просто 1, без суффикса M, иначе это создание файла размером в 200000 ПБ
dd if=/dev/zero of=./disk-image bs=1 count=0 seek=200G
Точно, так работает.

dlinyj@dlinyj-System:~/tmp/test$ dd if=/dev/zero of=./disk-image bs=1 count=0 seek=200M
0+0 записей считано
0+0 записей написано
скопировано 0 байт (0 B), 2,2231e-05 c, 0,0 kB/c
dlinyj@dlinyj-System:~/tmp/test$ ls -la
итого 8
drwxrwxr-x 2 dlinyj dlinyj 4096 нояб. 7 14:24.
drwxrwxr-x 15 dlinyj dlinyj 4096 нояб. 7 14:24…
-rw-rw-r-- 1 dlinyj dlinyj 209715200 нояб. 7 14:26 disk-image
dlinyj@dlinyj-System:~/tmp/test$

Да, это работает. Спасибо!
fallocate -l 1G swapfile

так прокатит (если у вас btrfs, ext4, ocfs2, или xfs)
Почему?
Swap files cannot be sparse; they must be fully allocated before using them.
Ubuntu 12.04, в связи с недостатком места для размещения 200 гигабайт, решил обойтись 200 мегабайтами.

dlinyj@dlinyj-System:~/tmp/test$ dd if=/dev/zero of=./disk-image bs=1M count=0 seek=200M
dd: не удалось выполнить отсечение на 219902325555200 байт в выходном файле «./disk-image»: Файл слишком велик
dlinyj@dlinyj-System:~/tmp/test$ ls -la
итого 8
drwxrwxr-x 2 dlinyj dlinyj 4096 нояб. 7 14:24.
drwxrwxr-x 15 dlinyj dlinyj 4096 нояб. 7 14:24…
-rw-rw-r-- 1 dlinyj dlinyj 0 нояб. 7 14:24 disk-image
dlinyj@dlinyj-System:~/tmp/test$

bs=1M
Выше написали же. У вас файл 2000G получается.
Да, я уже понял. Спасибо!
а я теперь всегда буду… ну вы поняли :)
Я, кстати, понял чем отличается файл, созданный с помощью seek от файла честно заполненного нулями…
$ ls -lh disk*
-rw-rw-r-- 1 seriy seriy 600G нояб.  7 14:29 disk-image
-rw-rw-r-- 1 seriy seriy 600G нояб.  7 14:33 disk-image2
-rw-rw-r-- 1 seriy seriy 600G нояб.  7 14:33 disk-image3
-rw-rw-r-- 1 seriy seriy 600G нояб.  7 14:33 disk-image4
$ df -h | grep /home
/dev/sda5        1,8T         822G  900G           48% /home

Т.е. файл хоть и весит 600Гб, но места на диске не занимает. Возможно это какая-то оптимизация файловой системы, не знаю.
Это обычный sparse-файл
Да, это sparse file что, кстати, и отражено в его названии в статье ;-)

P. S. Почему коментарий можно редактировать, но нельзя удалить? Дубликат же получился :-(
А python'овские seek и write, как понимаю, тоже создадут такой файл? Иначе он никак не мог бы отработать быстрее.
НЛО прилетело и опубликовало эту надпись здесь
truncate -s 200G disk-image
Использую

find. | xargs rm

Пока не подводило.
Попробовал — отжирает память и ничего не удаляет.
Не исключаю, что от версии зависит.
find (GNU findutils) 4.4.2
find -type f -print0 | xargs -0 /bin/rm -f

А так?
А разница будет?
Когда запускается xargs? Когда find выдаст весь результат или по мере появления?
Сразу, но есть тонкости. Скорее всего, будет чуть быстрее.

Попробуйте ещё:

find. -type f -print0 | xargs -r0 ionice rm -f
А сделайте тоже самое на reiserfs 3
Или на xfs. Автору нужно правильно выбирать файловые системы под задачу.
Дык сами и попробуйте. Какая разница с какой файловой системы rm -r ./* загрузит 20 миллионов список файлов и уйдёт в своп?
Статья не о выборе правильной ФС, а, скорее, об инструментах для работы с ней.
НЛО прилетело и опубликовало эту надпись здесь
Между миллионом и 13 млн файлов существенная разница! Вы не смотрели сколько RAM занимает find при этом?

Мой опыт показывает, что find всегда строит в памяти полный список файлов в директории прежде чем начать проводить с ними какие-то операции.

Может расскажете как вы пришли к такому решению
НЛО прилетело и опубликовало эту надпись здесь
Попробовал. Отъело 3.5Гб и только после этого начало удалять. Не знаю весь список оно загрузило или нет, но то что это не лучше rm -r по моему очевидно.
НЛО прилетело и опубликовало эту надпись здесь
find не всегда строит, а смотрит на количество оставшейся памяти и пытается балансировать между минимизацией вызовов readdir и потреблением памяти. Попробуйте запустить его под ulimit — хорошо иллюстрирует.
Подскажите какие ulimit задавать?

попробовал ulimit -m $((1024 * 50)) — не помогло. Так же набирает по 500 Мб
с ulimit -v $((1024 * 50)) после 50Мб молча падает
Если речь о GNU'шном find, то он при своей работе заводит списки структур savedir_dirinfo, которые пытается инкрементально порождать на каждую директорию, начиная выделение с xmalloc на 16 байт, а затем растягивая получившуюся систему буферов с помощью extendbuf, которая в свою очередь выбирает размер нового буфера тупым нахождением округления сверху (в общем, практически чуть ли не первая реализация из классической книжки Кнута):

  while (newsize < wanted)
    {
      if (2 * newsize < newsize)
        xalloc_die ();
      newsize *= 2;
    }
  return newsize;

Дальше, если новый объем пытается выделиться или реаллоцироваться через xmalloc / xrealloc и если не получится это сделать, то find отнюдь не впадает в панику и не считает это критической ошибкой, а, напротив, считает, что все, памяти уже достаточно и возвращается к предыдущему объему — и вот тут-то и должен сработать механизм дампа всего накопившегося, если это возможно (разумеется, нужно отсутствие флага SavedirSort, иначе будет вызван qsort и будет делаться сортировка вывода, что в данном случае смерти подобно).

С точки зрения использования ulimit: -m в современных Linux вообще смысла не имеет, см. RLIMIT_RSS, можно попробовать -d (но тогда и смотреть надо на data segment и учесть, что там бывает только софт-лимит), ну и по идее должен работать -v — там просто проблема в том, что он еще и стек лимитирует и при исчерпании стека будет предсказуемо SIGSEGV — возможно, вы столкнулись именно с этой ситуацией. Можно попробовать лимитировать -v, но сделать -s побольше. Ну или вообще не трогать ulimit, а лимитировать через cgroups.
Попробовал ограничить через cgroups
sudo cgcreate -a $USER -g memory:tst
echo 700000000 > /sys/fs/cgroup/memory/tst/memory.limit_in_bytes
sudo cgexec -g memory:tst find /mnt/ext4/test_dir/ -delete

При отключенном swap процесс прибивается по достижении 700Мб, если swap включен — уходит в swap.
Но так ничего и не удаляет.
Если не поленюсь — запущу под виртуальной машиной.
Можете уточнить, что значит «прибивается»? Это все-таки SIGSEGV или oomkiller, скажем, у вас как-то агрессивно срабатывает?
Судя по syslog это oom killer

Nov 10 22:08:39 seriy-desktop kernel: [ 1772.927181] find invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_score_adj=0
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.927186] find cpuset=/ mems_allowed=0
..........
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.927269] Task in /tst killed as a result of limit of /tst
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.927272] memory: usage 292972kB, limit 292972kB, failcnt 55186
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.927274] memory+swap: usage 292972kB, limit 9007199254740991kB, failcnt 0
...........
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.949829] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.949893] [ 5616]     0  5616    77136    73379   2       0             0 find
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.949895] Memory cgroup out of memory: Kill process 5616 (find) score 974 or sacrifice child
Nov 10 22:08:39 seriy-desktop kernel: [ 1772.949898] Killed process 5616 (find) total-vm:308544kB, anon-rss:292736kB, file-rss:780kB

Ну, тогда как бы эксперимента не получается: oom killer убивает find еще до того, как он успеет узнать, что памяти ему не дали и поумерить свои аппетиты. Попробуйте выключить oom_killer для этой cgroup, что-то типа:

echo 1 >/sys/fs/cgroup/memory/tst/oom_control
echo 1 >/sys/fs/cgroup/memory/tst/memory.oom_control
Теперь дорастает до 300Мб и засыпает на __mem_cgroup_try_charge.
Ладно, по-моему отклонились от темы.
Нет причин вам не верить. Но, похоже, find не успокаивается пока не займёт всю доступную память, включая swap. Что есть не самое удачное поведение.
Ну, мне на самом деле самому интересно, что на современных системах получается. Насколько я понимаю, поведения вида «займем всю выданную память» с некоей авторегуляцией процесса занятия со стороны программы, на современных системах (и с точки зрения аппаратного развития — всякие там SMP, multi core и т.д., и с точки зрения программного — OOM killers, cgroups, поломанные setrlimit), мягко говоря, работает плохо.

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

А с C-based все получается именно что вот так грустно: либо непортабельно, либо не особенно работоспособно, либо и то, и другое…
А если так?
find /mnt/test_dir/ -delete
В статье есть такой пример. Опция -type f не влияет.
find -type f не всегда помогает, иногда приходится делать find -not -type d
>>>К сожалению, не нашел в Python функции для итеративного чтения директории, чему крайне удивлён; os.listdir() и os.walk() читают директорию целиком
Судя по документации, os.listdir() должна возвращать список сразу, в то время как os.walk() как раз отдаёт результат постепенно.
os.listdir(path) — Return a list containing the names of the entries in the directory given by path.
os.walk(top, topdown=True, onerror=None, followlinks=False) — Generate the file names in a directory tree by walking the tree either top-down or bottom-up. For each directory in the tree rooted at directory top (including top itself), it yields a 3-tuple (dirpath, dirnames, filenames).
Вот прям сейчас специально проверил
import os

for l in os.walk("/mnt/test_dir/"):
    print l

Жрет память, ничего не печатает
А glob.iglob не помогает?
Сам себе отвечу. Судя по всему glob использует тот же listdir. Так что не поможет.
Вы не выделили жирным.
it yields a 3-tuple (dirpath, dirnames, filenames).
filenames is a list of the names of the non-directory files in dirpath.
В Linux никак нельзя удалить файлы из папки, в Linux нет папок, как и мамок, как и дедок.
В Linux есть директории.
Нет никаких директорий, вам наврали, есть иноды с различными аттрибутами )
… и есть там только железяка, с куском рандомно намагниченных точек, вращающаяся в пространстве вокруг своей оси. И смотрите вы сейчас не на сайт, и даже не на браузер, а на тонкий слой жидких кристаллов, меняющих свою поляризацию в зависимости от электрических импульсов…
Да тоже не факт в случае SSD :)
И CRT-монитора :)
я гляжу виндузятник позвал дружков неудачников за указание ошибки.
неплохо-неплохо.
вот только от туповатых виндузятников директория папкой не станет.
Заголовок статьи я взял от первоначальной статьи habrahabr.ru/post/152193/
В тексте статьи везде использую «директория».
Да хоть откуда берите. Сразу палиться виндузятник. Папка — пьяный бред переводчиков какой-то из их недоос.
о, а не подскажете, как трезвый линуксоид в здравом уме перевел бы слово «folder»?
Неграмотный фанатик тоже сразу «палитЬся».

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

А ещё в Фигурнове было слово «каталог».
«директории», ежливчо, это ещё более пьяный бред причом даже не переводчика.

Правильное, русское, слово — каталоги.
Но всем пофик.
> «директории», ежливчо, это ещё более пьяный бред причом даже не переводчика.

Ну почему, Уфимская директория или Французская директория — очень даже не бред :)
Спасибо хорошая статья ))
Да прекратите уже размусоливать…

rm -rfd /path


100 раз уже и на опеннете писалось, и в предыдущем топике я об этом упоминал.
Я пробовал. У меня ругнулся что нет опции "-d".
$ rm --version rm (GNU coreutils) 8.13

Кстати, судя по ману (man 2 unlink), unlink не удаляет директории

ERRORS
....
       EISDIR pathname refers to a directory.  (This is  the  non-POSIX  value
              returned by Linux since 2.1.132.)

Не знаю, у меня вот rm (GNU coreutils) 7.4
И хоть ключика нет в --help, он есть и работает ровно так, как я того ожидаю.
Прочитал про него давным давно на LOR.
А исходники читать не пробовали? Нет там такой опции
Когда ее там нет, я вижу ошибку
rm: invalid option -- 'd'
while ((c = getopt_long (argc, argv, "dfirvIR", long_opts, NULL)) != -1)
    {
      switch (c)
        {
        case 'd':
          /* Ignore this option, for backward compatibility with
             coreutils 5.92.  FIXME: Some time after 2005, change this
             to report an error (or perhaps behave like FreeBSD does)
             instead of ignoring the option.  */
          break;

Собственно, опция-то есть! Нет реализации :)
Ну, я последний раз пользовался ею в дебиане 4-м, сейчас вся мелочь в memcache живет.
Тогда оно реально сработало и сильно облегчило мне жизнь.
>Some time after 2005, change this…

Ну, надо подождать до 2005-го, чего не ясно?
>… to report an error
Это исходник версии 7.4 (2006 год). В текущих версиях этого фрагмента нет, и rm ругается на опцию -d.
Вы что сказать то хотели?
А в мане от 8.5 (Debian 6.0.6) кстати есть.
-d, --directory
Удалять каталоги с помощью системного вызова unlink(2) вместо rmdir(2), и не требовать, чтобы каталог был пуст перед его разлинковкой. Работает только если у вас есть соответствующие привилегии. Поскольку разлинковка (разрыв связи) каталога приводит к тому, что все файлы в удаленном каталоге теряют ссылочную целостность, то будет благоразумно после этой операции проверить файловую систему командой fsck(8).

Но заметьте, советуют проверить диск :)
Это просто старый перевод, в английской (LANG=c man rm) этой опции нет, равно как и в выводе rm --help (для обоих языков) и, конечно же, в info-странице
Да, залез в исходники, нет кода :( Заколдовали… БСД рулит, там есть :)
Ключ -d есть во FreeBSD

$ man rm
RM(1)                   FreeBSD General Commands Manual                  RM(1)

NAME
     rm, unlink -- remove directory entries

SYNOPSIS
     rm [-f | -i] [-dIPRrvW] file ...
     unlink file

DESCRIPTION
     The rm utility attempts to remove the non-directory type files specified
     on the command line.  If the permissions of the file do not permit writ-
     ing, and the standard input device is a terminal, the user is prompted
     (on the standard error output) for confirmation.

     The options are as follows:

     -d      Attempt to remove directories as well as other types of files.
$ rm -rfd 4444/
rm: invalid option — 'd'
Try `rm --help' for more information.

$ cat /etc/lsb-release |grep DISTRIB_DESCRIPTION
DISTRIB_DESCRIPTION=«Ubuntu 12.04.1 LTS»

$ uname -a
Linux relgames 3.2.0-32-generic #51-Ubuntu SMP Wed Sep 26 21:33:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
Зачем выкладывать версию ядра в обсуждении особенностей парсинга программой коммандой строки?
Кстати, интересно вот что… После того как мы сделали rm -d у нас все айноды освободятся?
А fsck после этого не будет ли работать дольше чем rm -rf?
А после fsck не появятся ли все эти файлы в lost+found?
В общем, нужно проверять.
Тут проблема не в дольше или нет, а в том, что придется, возможно, размонтировать ФС :)
А вот интересно, в unix-е каталог, это тоже файл. Нужно попытаться этот файл каким-то образом обнулить.
>dir — не прокатит, конечно :) Но может через системный вызов какой?
Хотя, даже если это и удастся сделать, после этого, наверняка, придется использовать fsck и чистить lost+found.
Именно так.
Причом в lost+found образуется тежесамые миллионы файлов.
На какой файловой системе тестировали?

У меня была проблема с ext3.

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

Способы с rm тоже работали (удаляли файлы) но на время работы делали сервер неработоспособным из-за того, что удаление забивало полностью диск и другие процессы не могли нормально с него читать
В статье, если приглядеться, указано что ext4. Не думаю, что это сильно повлияло, но могу попробовать с ext3 тоже.
Для снижения нагрузки см 3-й пункт в выводах статьи.
ext3 и ext4 в плане удаления файлов сильно отличаются (по крайней мере по скорости выполнения точно)
Ок, попробую ext3

Но, опять таки, главная проблема не в скорости удаления/чтения, а в том накапливается список файлов в памяти или используется сразу.
Ещё необходимо мониторить free, т.к. память может отожрать само ядро.
Года три назад была ситуация, когда файлы сессий создавались, но не удалялись :D, в итоге на диске в 1ТБ было занято около 75% инодов. Сколько там было файлов не известно. Удаление стандартными средствами не давало результатов, либо было слишком медленным.

Ситуацию спас find, с поиском по инодам.

find . -inum 0000000 -exec rm -i {} \
Для того чтоб айнодов было больше можно уменьшить размер блока в ext4:

mkfs -t ext4 -b 2048

В этом случае минимальный размер папки будет не 4Kb а 2Kb а айнодов будет в 2 раза больше

или
mkfs -t ext4 -b 1024 

В этом случае минимальный размер папки будет 1Kb а айнодов будет в 4 раза больше
В статье упоминается опция -I, которая позволяет непосредственно задать нужное количество айнодов. Но я о ней узнал не сразу, поэтому использовал опции по умолчанию.
Спасибо за подсказку в личке, правильный ключ -N, а не -I.
Было такое очень давно (тоже с какими-то сессиями). Кажется помогло что-то типа
rm 00* потом rm 01* потом… rm ff*
ничего лучше на тот момент не придумал.
Для большого кол-ва элементов в exec'е find'а стоит использовать + вместо;

find /mnt/test_dir/ -type f -exec rm -v {} \+

Если верить ману, ведет себя схоже с xargs.
Работает в таком виде, если не надо удалять все файлы:
find /oth/monitor/ -name "*2013*.wav" -type f -exec rm -v {} \+
А как же Argument list too long в rm?
Возможно ли, что поведение rm зависит от ОС/ядра?
В случае rm -r /mnt/test_dir/ аргумент всего один — /mnt/test_dir/. Вот если использовать find или
rm -r /mnt/test_dir/* то да, получишь «Argument list too long».
Я в свое время использовал простейщий однострочник
for i in /mnt/test_dir/*; do rm -f $i; done
Конечно, не самый оптимальный вариант, т.к. удаляет по одному файлу, но проблема стояла остро и решить ее надо было прямо сейчас.
ФС была ext3, файлов не 5 миллионов, конечно, но не меньше 1 миллиона.
А когда отменили ARG_MAX?
смысл xargs не запускаться по 100 аргументов (-n100), а запускаться с столькими аргументами, сколько влезет в ARG_MAX.
вам можно было бы миллион, например, поставить, если нет ARG_MAX
find /var/lib/php/session -depth -mindepth 1 -maxdepth 1 -type f -ctime +ХХХ -execdir fuser -s {} 2>/dev/null \; -delete
До сих пор не могу понять этот шаман-код Плеска.
Заменил в коде
chdir("/mnt/test_dir"); на chdir(argv[1]);


Вызываю так, что позволяет рекурсивно обходить каталоги и зачищать их
find /backup/daily.5/ -type d -printf "Cleaning: %p\n" -exec /usr/bin/cleandir {} \;

rm -r /mnt/test_dir/

извините, но у вас в заголовке «как удалить файлы ИЗ папки», а приводите команду которая удаляет не только файлы но и папку.

ps я вижу, что статья 2012, а на дворе 2019

да, верно… но думаю для описанного в оригинальной статье случая это не столь важно.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории