LINUX.ORG.RU

Argument list too long

 


0

1

По следам недавнего поста на хабре, я погуглил, откуда же берется это ограничение на количество аргументов для rm.

Нашел вот такой пост:

Actually this is not a limitation of the rm command, but a kernel limitation on the size of the parameters of the command. Since I was performing shell globbing (selecting all the files with extension .wrk), this meant that the size of the command line arguments became bigger with the number of the files involved. For who cares this is defined by:
egrep ARG_MAX /usr/include/linux/limits.h
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */

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

find . -type f -exec rm -v {} \+
или
find . -type f -print0 | xargs -0 rm
Оба вариант, насколько я понял, все равно передают rm в качестве аргумента огромный список файлов. Разница лишь в разделителе имен - «terminated by a null character». Такая строка не подпадает под ARG_MAX что ли?

★★★★★

Оба вариант, насколько я понял, все равно передают rm в качестве аргумента огромный список файлов

Ты неправильно понял.

Deleted
()

Разница лишь в разделителе имен - «terminated by a null character»

Разница между двоими твоими строками в том, что в случае с exec команда для exec выделяется в дочерний от find процесс, а в случае с xargs, если я правильно помню пайпы, find выполняется в субоболочке, выхлоп из которой возвращается в текущую оболочку, где запускается xargs.

Deleted
()
Ответ на: комментарий от Deleted

Ну, и, возвращаясь, попадает на input этому самому xargs естессно.

Deleted
()

А, прошу прощения, не разглядел плюсик на конце выражения с exec — это скомпонует строку со всеми найденными аргументами, и подвержено лимиту ARG_MAX.

Deleted
()

На самом деле find разбивает { } + на порции и выполняет `command` для каждой из них.
man 1p find, info find
также man 1p xargs и info xargs.

ABW ★★★★★
()
Ответ на: комментарий от Deleted

Обе приведенные мной команды не подвержены лимиту. Сейчас «find . -type f -exec rm -v {} \+» удалил без проблем 500000 файлов в каталоге.

ostin ★★★★★
() автор топика
Ответ на: комментарий от ABW

Что получит «rm -v» в первом случае от find, один файл или список? Что получит «rm» от xargs во втором случае, один файл или список? Уже не раз видел комментарии по поводу именно этих двух вариантов, что здесь как раз каждый раз rm повторно не вызывается.

ostin ★★★★★
() автор топика

почему, в таком случае, без ошибки отрабатывают команды

Первая никаких списков аргументов не строит, а вторая разбивает список на разумные части (man xargs).

Eddy_Em ☆☆☆☆☆
()

По поводу первого варианта вот тебе выдержка из man find:

-exec command {} +
              This variant of the -exec action runs the specified command on the selected files, but the command line is built by  appending  each  selected  file
              name  at  the  end; the total number of invocations of the command will be much less than the number of matched files.  The command line is built in
              much the same way that xargs builds its command lines.  Only one instance of `{}' is allowed within the command.  The command  is  executed  in  the
              starting directory.

В общем, для rm оба варианта абсолютно равнозначны. С точки зрения производительности первый предпочтительней, т.к. не нужно создавать в баше лишнюю трубу и запускать xargs.

Eddy_Em ☆☆☆☆☆
()
Последнее исправление: Eddy_Em (всего исправлений: 1)
Ответ на: комментарий от Eddy_Em

Попробовал удалить 500 000 файлов, вот какие данные у меня получились:

find . -type f -exec rm -v {} \+
real  0m37.895s
user  0m3.908s
sys 0m19.224s

find . -type f -print0 | xargs -0 rm
real  0m19.024s
user  0m1.346s
sys 0m11.767s

Т.е. вторая быстрее.

ostin ★★★★★
() автор топика
Ответ на: комментарий от Eddy_Em

По-моему это из-за того, что они просто выполняют вызов exec по-разному.

Deleted
()
Ответ на: комментарий от ostin

The POSIX standard allows implementations to have a limit on the size of arguments to the exec functions. This limit could be as low as 4096 bytes including the size of the environment. For scripts to be portable, they must not rely on a larger value. However, I know of no implementation whose actual limit is that small. The --show-limits option can be used to discover the actual limits in force on the current system.

Видимо они вызывают exec частями по 4096 (или сколько захотят в лимитах ядра), но средствами баша типа set -x и вербозностью этого не увидеть.

Deleted
()
Ответ на: комментарий от Deleted

Добрые дяди из GNU позаботились о нас :3
А проприетарщики пусть страдают >:3

Deleted
()
Ответ на: комментарий от ostin

Нечестное сравнение

Почему в первом случае вызывается rm -v, а во втором rm? Куча времени уходит на печать списка удаляемых файлов.

Добавьте в сравнение ещё find . -type f -delete

anonymous
()
Ответ на: комментарий от ostin

Если в таком порядке и запускал — то это повлиял кэш фс, и результат некорректен.

anonymous
()
Ответ на: комментарий от Eddy_Em

Вот удаление 1 000 000 файлов, каждый тест проводил после ребута машины:

find . -type f -exec rm {} \+
real  4m32.491s
user  0m5.496s
sys 0m33.948s

find . -type f -print0 | xargs -0 rm
real  4m14.397s
user  0m4.122s
sys 0m27.320s

find . -type f -delete
real  2m30.783s
user  0m2.613s
sys 0m18.592s

В общем, у нас есть победитель, опция -delete.

ostin ★★★★★
() автор топика
Ответ на: комментарий от ostin

В общем, у нас есть победитель, опция -delete

Вполне логично: не приходится нарезать из выхлопа строку аргументов и вызывать внешнюю программу.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Зато странно, что find | xargs, которая гоняет данные через пайп и создаёт на один процесс больше, быстрее, чем find -exec

anonymous
()
Ответ на: комментарий от anonymous

Я подозреваю, что find просто создает более короткий список аргументов (а, следовательно, чаще вызывает rm), нежели xargs

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.