Делаем скрипт на Bash параллельным с помощью xargs
Тем, кто когда-нибудь пытался написать параллельный скрипт на Bash, должен быть знаком параметр -P утилиты xargs. В сочетании с find он позволяет выполнять заданную команду для каждого файла, распределяя эти команды между указанным количеством процессов. Эта схема распараллеливания идеально подходит, если нужно, скажем, сковертировать все файлы в директории.
Когда я начал писать такие скрипты, то стал испытывать определенное неудобство. Дело в том, что в большинстве случаев команда, подаваемая на вход xargs, оказывается сложнее вызова определенной утилиты с аргументами. То и дело получается целый набор команд, особенно если требуется отображать ход выполнения процесса, реагировать на ошибки. В итоге для обработки одного файла создается отдельный скрипт в дополнение к скрипту, в котором участвует вызов xargs.
Я задумался, как можно соединить эти два скрипта в один. Хотелось бы, чтобы xargs принимал в качестве команды функцию Bash, но это не работает. Следуя логике, получается, что если у меня не должно быть ничего, кроме моего скрипта, то он и должен подаваться на вход xargs. Для того, чтобы отделить вызовы обработки списка файлов и отдельного файла, вводится специальный аргумент. Если на вход подается число больше нуля, то оно является количеством потоков обработки списка, если ноль, то обслуживается отдельный файл.
Если Вы захотите использовать этот прием, то в большинстве случаев Вам будет достаточно вставить в свой скрипт такой код:
function process { default_np=4 np="$1"; shift if [ -z "$np" ]; then np=$default_np; fi if [ "$np" == "0" ] then process_item "$@" else process_list "$np" "$@" fi } process "$@"
Перед этим Вы должны написать две функции — process_item для обработки отдельного файла и process_list для формирования и обработки списка файлов. process_list получит все аргументы скрипта, начиная со второго, и должна вызвать xargs. Скачайте демонстрационный скрипт, чтобы стало понятно, как это делать.
Предложения по улучшению приветствуются!
Никита Мельниченко.
Комментирование приостановлено