Как запустить несколько программ параллельно из bash-скрипта?
Я пытаюсь написать файл .sh, который запускает несколько программ одновременно.
Я пробовал следующий код:
prog1
prog2
Но в этом случае сначала выполняется prog1, а затем, после его завершения, начинает выполняться prog2...
Как я могу запустить их параллельно?
5 ответ(ов)
Чтобы запустить несколько программ параллельно, используйте следующий синтаксис:
prog1 &
prog2 &
Если вам нужно, чтобы ваш скрипт дожидался завершения этих программ, можно добавить команду:
wait
в том месте, где вы хотите, чтобы скрипт ждал их завершения. Например:
prog1 &
prog2 &
# (выполняем другие действия, пока 'prog1' и 'prog2' работают
# в фоновом режиме)
...
# (Теперь нам нужны результаты 'prog1' и 'prog2'
# перед тем, как продолжить, так что дожидаемся их
# завершения)
wait
Таким образом, ваш скрипт не продолжит выполняться, пока обе программы не завершатся.
Команда:
prog1 & prog2 && fg
выполнит следующие действия:
- Запустит
prog1
. - Отправит его в фоновый режим, при этом будет продолжать выводить его вывод на экран.
- Запустит
prog2
, который останется в переднем плане, что позволит вам закрыть его с помощьюctrl-c
. - Когда вы закроете
prog2
, управление вернется кprog1
, который будет снова в переднем плане, и вы сможете также закрыть его с помощьюctrl-c
.
Если вы хотите иметь возможность легко запускать и останавливать несколько процессов с помощью ctrl-c
, вот мой любимый метод: создайте несколько фоновых процессов в подшелле (…)
и перехватите сигнал SIGINT
, чтобы выполнить kill 0
, который завершит все процессы, запущенные в группе этого подшелла:
(trap 'kill 0' SIGINT; prog1 & prog2 & prog3)
Вы можете иметь сложные структуры выполнения процессов, и всё закроется с помощью одной комбинации ctrl-c
(только убедитесь, что последний процесс выполняется в фоновом режиме, то есть не добавляйте &
после prog1.3
):
(trap 'kill 0' SIGINT; prog1.1 && prog1.2 & (prog2.1 | prog2.2 || prog2.3) & prog1.3)
Если существует вероятность того, что последняя команда может завершиться раньше времени, и вы хотите, чтобы всё остальное продолжало работать, добавьте wait
в качестве последней команды. В следующем примере команда sleep 2
завершится первой, убив sleep 4
до того, как она завершится; добавление wait
позволяет обоим процессам выполниться до конца:
(trap 'kill 0' SIGINT; sleep 4 & sleep 2 & wait)
Этот подход позволяет вам более эффективно управлять множественными процессами в вашем скрипте.
Вы можете использовать команду wait
:
some_command &
P1=$!
other_command &
P2=$!
wait $P1 $P2
В этом примере мы присваиваем идентификаторы процессов (PID) фоновых программ переменным ($!
возвращает PID последнего запущенного процесса), а затем команда wait
ожидает их завершения. Это удобно тем, что если вы остановите скрипт, процессы тоже будут завершены!
Вы можете использовать следующую функцию, чтобы запускать максимум n процессов параллельно (в примере n=4):
max_children=4
function parallel {
local time1=$(date +"%H:%M:%S")
local time2=""
# Для примера я использую $2 в качестве описания, вы можете использовать другую переменную, если это необходимо
echo "начинаю $2 ($time1)..."
"$@" && time2=$(date +"%H:%M:%S") && echo "завершение $2 ($time1 -- $time2)..." &
local my_pid=$$
local children=$(ps -eo ppid | grep -w $my_pid | wc -w)
children=$((children-1))
if [[ $children -ge $max_children ]]; then
wait -n
fi
}
parallel sleep 5
parallel sleep 6
parallel sleep 7
parallel sleep 8
parallel sleep 9
wait
Если значение max_children
установлено равным количеству ядер, эта функция поможет избежать простоя ядер. Такой подход позволит эффективно использовать ресурсы вашего компьютера, запуская процессы параллельно, не превышая заданное количество одновременно работающих процессов.
Как изменить цвет вывода echo в Linux
Как работает "cat << EOF" в bash?
Передача параметров в функцию Bash
Расширение переменных внутри одинарных кавычек в команде Bash
Как разделить большой текстовый файл на меньшие файлы с равным количеством строк?