Вопрос или проблема
Утилита Unix find(1)
очень полезна, позволяя мне выполнять действия над многими файлами, которые соответствуют определённым критериям, например:
find /dump -type f -name '*.xml' -exec java -jar ProcessFile.jar {} \;
Приведённый выше пример может запускать скрипт или инструмент для каждого XML-файла в определённом каталоге.
Допустим, мой скрипт/программа требует много времени процессора, и у меня 8 процессоров. Было бы неплохо обрабатывать до 8 файлов одновременно.
GNU Make позволяет выполнять параллельную обработку заданий с флагом -j
, но find
, похоже, не имеет такой функциональности. Существует ли альтернативный универсальный метод планирования заданий для решения этой задачи?
xargs
с опцией -P
(количество процессов). Допустим, я хочу сжать все журналы в каталоге на машине с 4 процессорами:
find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2
Вы также можете указать -n <number>
для максимального количества рабочих единиц на процесс. Допустим, у меня было 2500 файлов, и я указал:
find . -name '*.log' -mtime +3 -print0 | xargs -0 -n 500 -P 4 bzip2
Это запустит 4 процесса bzip2
, каждый из которых будет обработан на 500 файлов, и когда первый завершится, будет запущен следующий для последних 500 файлов.
Не знаю, почему предыдущий ответ использует xargs
и make
, у вас же два параллельных механизма!
GNU parallel тоже может помочь.
find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}
Обратите внимание, что без аргумента -j8
parallel
по умолчанию использует количество ядер на вашем компьютере 🙂
Нет необходимости “исправлять” find
; используйте сам make
для обработки параллелизма.
Пусть ваш процесс создаёт файл журнала или какой-то другой файл вывода, затем используйте Makefile, подобный этому:
.SUFFIXES: .xml .out
.xml.out:
java -jar ProcessFile.jar $< 1> $@
и вызывается так:
find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8
Более того, если вы убедитесь, что файл вывода создаётся только при успешном завершении процесса Java, вы можете воспользоваться обработкой зависимостей в make
, чтобы гарантировать, что в следующий раз будут обрабатываться только необработанные файлы.
У команды find есть параллельная опция, которую вы можете использовать напрямую с помощью символа “+”; без xargs. В сочетании с grep она может быстро проходить через ваше дерево, искомые совпадения. Например, если я ищу все файлы в каталоге исходников, содержащие строку ‘foo’, я могу вызвать
find sources -type f -exec grep -H foo {} +
Все предложенные варианты обеспечивают параллельное выполнение, но если ваше дерево файлов достаточно велико, узким местом может стать сам find. Один мой коллега написал locar как параллельный поиск, который очень полезен, когда ваша файловая система может выполнять сканирование параллельно. Это может не помочь, если ваша файловая система расположена на одном HDD, но если это устройство RAID, SSD или, лучше, распределённая файловая система, это будет очень полезно.
locar будет выполнять сканирование файлов параллельно в нескольких каталогах, так что вы получите список файлов быстрее и сможете затем комбинировать это с xargs или parallel для параллельного выполнения.
Ответ или решение
Улучшенная утилита Unix ‘find’ с параллельной обработкой
Утилита Unix find
является неотъемлемым инструментом для поиска и обработки файлов в файловой системе. Однако, как показано в вышеописанном примере, в случае, если ваша программа требует много вычислительных ресурсов, полезно обрабатывать несколько файлов одновременно, особенно если вы используете многоядерный процессор. В данном руководстве мы рассмотрим различные подходы к параллельной обработке файлов с помощью find
.
Использование xargs
для параллельной обработки
Один из самых простых и эффективных способов обработки множества файлов параллельно — это использование утилиты xargs
с параметрами -P
и -n
. Эти параметры позволяют запустить несколько процессов одновременно.
Пример команды:
find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2
В этом примере find
ищет файлы с расширением .log
, которые старше 3 дней, и передает их в xargs
. Опция -P 4
указывает xargs
запускать до 4 процессов bzip2
одновременно, а -n
позволяет указать количество файлов, передаваемых в каждый процесс.
Использование GNU Parallel
Если вы ищете более мощный инструмент, стоит обратить внимание на GNU Parallel
. Эта утилита специально предназначена для распределения работы между несколькими процессами.
Пример использования:
find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}
Здесь флаг -j8
задает количество одновременно выполняемых задач, что позволяет использовать все доступные ресурсы вашего процессора.
Интеграция с make
Еще один подход к параллельной обработке включает использование системы сборки make
. Создайте Makefile
, который управляет зависимостями и параллельным выполнением.
Пример Makefile
может выглядеть так:
.SUFFIXES: .xml .out
.xml.out:
java -jar ProcessFile.jar $< > $@
Таким образом, параллельный процесс может быть инициирован через find
и make
:
find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8
Эта комбинация использует функционал make
для автоматического отслеживания завершенных задач и обеспечения вновь обрабатываемых файлов только в случае, если их выходные файлы еще не были созданы.
Оригинальная возможность find
с параллельной обработкой
Также стоит упомянуть, что в последнем обновлении find
добавлена возможность параллельной обработки с использованием символа +
в конце операции -exec
:
find sources -type f -exec grep -H foo {} +
Эта команда будет более эффективной, так как find
будет обрабатывать файлы в пакетном режиме, снижая накладные расходы на запуск процессов.
Использование Locar для параллельного поиска
Если вам необходимо оптимизировать процесс поиска файлов в больших директориях, стоит рассмотреть возможность использования инструмента locar
. Этот инструмент позволяет выполнять параллельный поиск в файловой системе, что особенно полезно в случае работы с RAID-массивами или SSD.
Заключение
В этом руководстве рассмотрены различные методы параллельной обработки файлов в Unix, используя утилиты find
, xargs
, GNU Parallel
, и make
. Выбор подходящего метода будет зависеть от конкретных требований вашего проекта, рабочей нагрузки и архитектуры вашего оборудования. При правильном использовании эти инструменты могут значительно сократить время обработки файловых операций и повысить общую производительность системы.