Bash script параллельные команды обработки

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

#!/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 строкам, этот script динамически генерируется, поэтому я могу выполнять любую математику, которую я хочу на ней, пока она сгенерирована, но НЕОБХОДИМО использовать wget, это был просто пример, поэтому любое решение, специфичное для wget, не принесет мне никакой пользы.

Ответ 1

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

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

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

Из manual:

wait [jobspec or pid ...]

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

Ответ 2

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

Ответ 3

Фактически, xargs может запускать команды параллельно для вас. Для этого есть специальная опция командной строки -P max_procs. См. man xargs.

Ответ 4

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

wait

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