Bash скрипт обрабатывает ограниченное количество команд параллельно

У меня есть скрипт bash, который выглядит так:

#!/bin/bash
wget LINK1 >/dev/null 2>&1
wget LINK2 >/dev/null 2>&1
wget LINK3 >/dev/null 2>&1
wget LINK4 >/dev/null 2>&1
# ..
# ..
wget LINK4000 >/dev/null 2>&1

Но обработка каждой строки до тех пор, пока команда не закончена, а переход к следующей занимает очень много времени, я хочу обработать, например, 20 строк одновременно, а затем, когда они завершатся, будут обработаны еще 20 строк.

Я думал о wget LINK1 >/dev/null 2>&1 & чтобы отправить команду в фоновый режим и продолжить, но здесь 4000 строк, это означает, что у меня будут проблемы с производительностью, не говоря уже об ограничении количества процессов, которые я должен запускать одновременно, так что это не очень хорошая идея.

Одним из решений, о котором я сейчас думаю, является проверка, выполняется ли еще одна из команд или нет, например, после 20 строк я могу добавить этот цикл:

while [  $(ps -ef | grep KEYWORD | grep -v grep | wc -l) -gt 0 ]; do
sleep 1
done

Конечно, в этом случае мне нужно будет добавить & в конец строки! Но я чувствую, что это не правильный способ сделать это.

Итак, как мне на самом деле сгруппировать каждые 20 строк и ждать, пока они закончат, прежде чем перейти к следующим 20 строкам, этот сценарий генерируется динамически, поэтому я могу делать с ним все, что захочу, пока он генерируется, но он НЕ ДОЛЖЕН используйте wget, это был просто пример, так что любое решение, специфичное для wget, не принесет мне пользы.

4 ответа

Решение

Использовать wait встроенный:

process1 &
process2 &
process3 &
process4 &
wait
process5 &
process6 &
process7 &
process8 &
wait

Для приведенного выше примера 4 процесса process1... process4 будет запущен в фоновом режиме, и оболочка будет ждать, пока они не будут завершены, прежде чем начать следующий набор.

Из руководства GNU:

wait [jobspec or pid ...]

Дождитесь завершения дочернего процесса, заданного каждым идентификатором процесса pid или спецификацией задания, и верните состояние завершения последней ожидаемой команды. Если задана спецификация задания, все процессы в задании ожидаются. Если аргументы не указаны, ожидаются все активные в данный момент дочерние процессы, а статус возврата равен нулю. Если ни jobspec, ни pid не указывают активный дочерний процесс оболочки, возвращаемое состояние - 127.

Смотрите параллельно. Его синтаксис похож на xargs, но он запускает команды параллельно.

По факту, xargs может выполнять команды параллельно для вас. Есть специальный -P max_procs опция командной строки для этого. Увидеть man xargs,

Вы можете запустить 20 процессов и использовать команду:

wait

Ваш сценарий будет ждать и продолжать, когда все ваши фоновые задания будут завершены.

Другие вопросы по тегам