Поиск завершается неудачно с «Too Many Arguments» в Shell Script, но не при запуске непосредственно в терминале

476
Nestarion

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

#!/bin/bash find /some/directory/with/pictures/* -exec rm -rf {} \+ 

Я проверил это, чтобы работать на рабочей станции для разработки только с ~ 250 МБ изображений (30 изображений).

Поскольку на рабочих станциях этот сценарий не запущен, у них много образов, порядка нескольких сотен гигабайт. Это означает, что когда findон выполняется через скрипт оболочки, он останавливается и говорит «Too Many Arguments».

Я потратил много времени, пытаясь выяснить, почему (пробуя xargs, проверяя, изменилось ли что-то +на ;что-то и т. Д.), Единственное, чего я не пытался, это на самом деле входить в каталог через скрипт оболочки, чтобы вообще не использовать find. Я думаю, что «Too Many Arguments» имеет смысл - кажется, что количество аргументов ограничено, и у меня ~ 33 000 файлов на одной рабочей станции, на которой я проверяю эту концепцию.

Чтобы еще больше запутать меня, выполнение find ./ -exec rm -rf {} \;в самом каталоге через Терминал работает (медленно).

Я выполнил удаление, используя Терминал, поэтому я не беспокоюсь о процессе в будущем (он не даст около 33 тыс. Снимков в день), но я хочу знать, почему find работает в Терминале с 33 Кб аргументы, но не в сценарии оболочки.

2
Ваш скрипт и то, что вы выполняете в каталоге, не совпадают, `*` в вашем скрипте может вызывать расширение оболочки, которое может переполнить ограничение длины командной строки. Mokubai 6 лет назад 2
Будет ли изменение строки сценария оболочки на `find ./some/directory/with/pictures/ -exec rm -rf {} \ +` эквивалентно? У меня были проблемы с более ранними итерациями, когда я также удалял папку, содержащую файлы. Изменить: это не эквивалентно. Удаляет папку, как я ожидал. Nestarion 6 лет назад 0
@Nestarion Попробуйте `find ./some/directory/with/pictures/ -mindepth 1 -exec rm -rf {} \ +` (конечно, в тестовой директории). `-Mindepth 1` должен препятствовать удалению самого каталога. Gordon Davisson 6 лет назад 0
`find. / some / directory / with / pictures /` не работает, но удаление периода работает, когда я добавил `-mindepth 1`, как вы предложили. Но этот вопрос был больше о том, почему и как `find` ограничен, а не синтаксис моей команды (хотя это связано). Nestarion 6 лет назад 0

1 ответ на вопрос

0
cawwot

Вы столкнулись с проблемой * nix " слишком много открытых файлов "! Macos имеет ограничения на количество файлов, которые процесс может открывать одновременно. Это похоже на ulimitвзаимодействие с Init в большинстве систем Linux.

Эти ограничения устанавливаются отдельно для терминала и для приложений на основе файловой системы. Ограничения по умолчанию для каждого процесса наследуются от launchd на Mac (начиная с Leopard или около того), и вы можете увидеть их как скомпилированные с помощьюsudo launchctl limit

Есть способы изменить это поведение, например, Как постоянно контролировать максимальное потребление системных ресурсов на Mac? , а какая команда управляет пределами открытых файлов?

Ссылки, которые вы предоставили, очень полезны. Это именно то, что я искал! Nestarion 6 лет назад 0
-1. В этом случае `find` даже не открывает файлы, полученные в результате расширения` * `; это только подтверждает, что они существуют, это действие требует чтения записей каталога. Инструмент открывает каталоги (если есть), но делает это один за другим: закрывает один перед открытием следующего. `rm` также не открывает файлы, он связывает их один за другим. «Слишком много аргументов» - это не «Слишком много открытых файлов». Kamil Maciorowski 6 лет назад 1
@KamilMaciorowski В соответствии с `man find` в моей системе find _" GNU find ищет дерево каталогов с корнем в каждой заданной начальной точке, оценивая данное выражение слева направо в соответствии с правилами приоритета (see section ОПЕРАТОРЫ) до результат известен (левая часть ложна для и операции, истинна для или), после чего поиск переходит к следующему имени файла. "_ Это означает, что все дерево из базового каталога является _open_ во время выполнения команды ( к определению слова _open_). cawwot 6 лет назад 0
@cawwot `find` не нужно открывать файлы для поиска * деревьев каталогов *. Никакая часть команды OP фактически не открывает файл, который был найден. Исполняемые файлы (`find`,` rm`) необходимо открыть с помощью некоторых дополнительных файлов (например, библиотек, локалей и т. Д.), Но это все. Kamil Maciorowski 6 лет назад 0
@KamilMaciorowski В разветвленном файле файловой системы _descriptors_ открываются такими командами, как `find`,` rm` и т. Д. На компьютерах Mac используется HFS (или HFS + на более новых macs), у Apple есть то, что Apple называет [Resource forks] (https: //en.wikipedia) .org / wiki / Resource_fork), которые открываются командами файловой системы, по одной для каждого файла (обычно). cawwot 6 лет назад 0
Вы становитесь ближе, чтобы убедить меня, что ваш ответ может быть правильным. Тем не менее, я серьезно сомневаюсь, что `find` или` rm` (или драйвер файловой системы) должны держать так много дескрипторов открытыми одновременно, чтобы это достигло предела. Вменяемые инструменты открывали и закрывали их последовательно (почти) один за другим. Вы хотите сказать, что компьютеры Mac с HFS / HFS + подвержены истощению ресурсов во время такой базовой операции, как обход дерева каталогов или удаление группы файлов? Kamil Maciorowski 6 лет назад 0
@KamilMaciorowski 1/2, обращая особое внимание на [rm] (https://github.com/openbsd/src/blob/master/bin/rm/rm.c), мы видим, что он использует из [limit.h ] (http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html) с учетом «Максимального количества файлов, которые один процесс может открыть в любой момент времени». cawwot 6 лет назад 0
@KamilMaciorowski 2/2 Однако у [find] (https://github.com/torvalds/linux/blob/master/fs/ubifs/find.c) такого ограничения нет, и оно ограничено только максимальным размером кучи и max_int. , В частности, мы можем видеть в функции ubifs_find_free_space (начиная со строки 493), что файловый дескриптор открывается для каждого _match_ критерия `find` (в конце концов, именно так файлы сопоставляются с вашими критериями` find`). Проблема с ОП, скорее всего, связана с максимальным размером совпадений. cawwot 6 лет назад 0
Я не программист, но: (A) я не могу найти `OPEN_MAX` в` rm.c`, на который вы ссылаетесь. (B) этот `find.c` является частью [UBIFS] (https://en.wikipedia.org/wiki/UBIFS). Я не знаю, почему это должно иметь значение в контексте `find (1)` и HFS. Kamil Maciorowski 6 лет назад 0
@KamilMaciorowski ах, вы правы, я видел пределы. И я предположил. Однако, глядя на функцию rm_tree `rm` (начальная строка 131), он никогда не строит дерево, а просто прогуливает его по элементам. Это для сравнения, чтобы найти (из [findutils] (https://ftp.gnu.org/pub/gnu/findutils/), который является пакетом, включенным в macos, я почти уверен, что я связался с неправильной находкой до). tree.c принимает все дерево, регистрируя каждый файл по мере его поступления, и это, если я не ошибаюсь, откроет каждый файл и ветвь ресурса dir в inode, пока он не закончит принимать, проходить и оптимизировать дерево. cawwot 6 лет назад 0
Опять же, я не программист, но: (C) Самая первая строка `tree.c` говорит` tree.c - вспомогательные функции для построения и оценки дерева выражений`. Дерево выражений организует операнды, а не файлы / каталоги. (D) Mac по умолчанию использует BSD `find`. Я считаю, что вы можете установить утилиты GNU по требованию, хотя. Kamil Maciorowski 6 лет назад 0
@KamilMaciorowski Я не уверен на 100%, я не программист, и у меня нет Mac прямо сейчас, чтобы увидеть лично. Однако мне кажется, что BSD `find` делает более или менее то же самое, но вместо построения дерева он запускает цепочки исполнителей сравнения (что дает сопоставимое поведение с точки зрения открываемых файлов). Я открыт для того, чтобы быть доказанным неправым, это просто «похоже» на то, что здесь происходит со мной. cawwot 5 лет назад 0