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
Ваш сценарий будет ждать и продолжать, когда все ваши фоновые задания будут завершены.