Как вы запускаете несколько программ параллельно из сценария Bash? - PullRequest
195 голосов
/ 09 июня 2010

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

Я пробовал это

prog1 
prog2

Но запускается prog1, затем ждет, пока prog1 завершится, а затем запускает prog2 ...

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

Ответы [ 13 ]

258 голосов
/ 05 апреля 2011

Как насчет:

prog1 & prog2 && fg

Это будет:

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

С GNU Parallel http://www.gnu.org/software/parallel/ это так же просто, как:

(echo prog1; echo prog2) | parallel

Или, если вы предпочитаете:

parallel ::: prog1 prog2

Подробнее:

  • Посмотрите вступительное видео для быстрого ознакомления: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
  • Пройдите учебник (man parallel_tutorial).Ваша командная строка будет любить вас за это.
53 голосов
/ 20 января 2017

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

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

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

17 голосов
/ 27 августа 2018

Если вы хотите иметь возможность легко запускать и завершать несколько процессов с помощью ctrl-c, это мой любимый метод: порождать несколько фоновых процессов в подоболочке (…) и ловушку SIGINT для выполнения kill 0, чтоуничтожит все, что появилось в группе subshell:

(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)
9 голосов
/ 09 июня 2010
#!/bin/bash
prog1 & 2> .errorprog1.log; prog2 & 2> .errorprog2.log

Перенаправлять ошибки в отдельные журналы.

8 голосов
/ 09 июня 2010

Существует очень полезная программа, которая вызывает nohup.

     nohup - run a command immune to hangups, with output to a non-tty
7 голосов
/ 07 февраля 2017

Вот функция, которую я использую для параллельного запуска при максимальном n-процессе (в примере n = 4):

max_children=4

function parallel {
  local time1=$(date +"%H:%M:%S")
  local time2=""

  # for the sake of the example, I'm using $2 as a description, you may be interested in other description
  echo "starting $2 ($time1)..."
  "$@" && time2=$(date +"%H:%M:%S") && echo "finishing $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 задано количество ядер, эта функция будет пытаться избежать незанятых ядер.

7 голосов
/ 10 июня 2010

Вы можете попробовать ppss .ppss довольно мощный - вы даже можете создать мини-кластер.xargs -P также может быть полезен, если вам нужно выполнить партию смущающей параллельной обработки.

6 голосов
/ 23 мая 2017

xargs -P <n> позволяет вам запускать <n> команды параллельно.

Хотя -P является нестандартным вариантом, его поддерживают как реализации GNU (Linux), так и macOS / BSD.

В следующем примере:

  • выполняет одновременно максимум 3 команды одновременно,
  • с дополнительными командами, запускаемыми только после завершения ранее запущенного процесса.
time xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF

Вывод выглядит примерно так:

1   # output from 1st command 
4   # output from *last* command, which started as soon as the count dropped below 3
2   # output from 2nd command
3   # output from 3rd command

real    0m3.012s
user    0m0.011s
sys 0m0.008s

Время показывает, что команды выполнялись параллельно (последняя команда была запущена только после первой из оригинальных3 завершается, но выполняется очень быстро).

Сама команда xargs не вернется, пока все команды не будут завершены, но вы можете выполнить ее в фоновом режиме, завершив ее с помощью оператора управления &, а затемиспользуя встроенную функцию wait для ожидания завершения всей команды xargs.

{
  xargs -P 3 -I {} sh -c 'eval "$1"' - {} <<'EOF'
sleep 1; echo 1
sleep 2; echo 2
sleep 3; echo 3
echo 4
EOF
} &

# Script execution continues here while `xargs` is running 
# in the background.
echo "Waiting for commands to finish..."

# Wait for `xargs` to finish, via special variable $!, which contains
# the PID of the most recently started background process.
wait $!

Примечание:

  • BSD / macOS xargs требует от васуказать количество команд дляпараллельный запуск явно , тогда как GNU xargs позволяет указать -P 0 для одновременного выполнения максимально возможного числа .

  • Выходные данные параллельно запущенных процессов поступают , так как он генерируется , поэтому он будет непредсказуемо перемеженным .

    • GNU parallel, как указано в Ответ Оле (* не входит в стандартную комплектацию большинства платформ), удобно сериализует (группирует) выходные данные для каждого процесса и предлагает множество дополнительных функций.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...