5

Как запустить несколько программ параллельно из bash-скрипта?

13

Я пытаюсь написать файл .sh, который запускает несколько программ одновременно.

Я пробовал следующий код:

prog1 
prog2

Но в этом случае сначала выполняется prog1, а затем, после его завершения, начинает выполняться prog2...

Как я могу запустить их параллельно?

5 ответ(ов)

5

Чтобы запустить несколько программ параллельно, используйте следующий синтаксис:

prog1 &
prog2 &

Если вам нужно, чтобы ваш скрипт дожидался завершения этих программ, можно добавить команду:

wait

в том месте, где вы хотите, чтобы скрипт ждал их завершения. Например:

prog1 &
prog2 &
# (выполняем другие действия, пока 'prog1' и 'prog2' работают 
# в фоновом режиме)
...
# (Теперь нам нужны результаты 'prog1' и 'prog2'
# перед тем, как продолжить, так что дожидаемся их 
# завершения)
wait

Таким образом, ваш скрипт не продолжит выполняться, пока обе программы не завершатся.

5

Команда:

prog1 & prog2 && fg

выполнит следующие действия:

  1. Запустит prog1.
  2. Отправит его в фоновый режим, при этом будет продолжать выводить его вывод на экран.
  3. Запустит prog2, который останется в переднем плане, что позволит вам закрыть его с помощью ctrl-c.
  4. Когда вы закроете prog2, управление вернется к prog1, который будет снова в переднем плане, и вы сможете также закрыть его с помощью ctrl-c.
3

Если вы хотите иметь возможность легко запускать и останавливать несколько процессов с помощью 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)

Этот подход позволяет вам более эффективно управлять множественными процессами в вашем скрипте.

1

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

some_command &
P1=$!
other_command &
P2=$!
wait $P1 $P2

В этом примере мы присваиваем идентификаторы процессов (PID) фоновых программ переменным ($! возвращает PID последнего запущенного процесса), а затем команда wait ожидает их завершения. Это удобно тем, что если вы остановите скрипт, процессы тоже будут завершены!

0

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь