Как ограничить параллельные задания

Как ограничить параллельные задания

У меня есть hosts, содержащий файл, /tmp/hostlistкоторый, скажем, требует имя пользователя и пароль для входа в систему, и я использую команду expect для входа в hosts и выполнения команды, и получаю, как показано ниже в моем скрипте bash.

)

VAR=$(expect -c "$script")

echo "$VAR" >/tmp/outexp
-----------------

Я могу справиться с параллельным выполнением -

while IFS= read -r i
do
        ( export server_name=`echo $i`;echo "connecting to $i";expect -c 
wait

Есть ли способ ограничить количество хостов одновременно? Например, предположим, у меня есть 1000 хостов в файле... и я хочу выполнить набор из 100 хостов за раз, чтобы завершить 1000 хостов...

решение1

С помощью GNU Parallel вы бы сделали что-то вроде:

[compute $script]
export script
run_one() {
  i="$1"
  export server_name=`echo $i`
  echo "connecting to $i"
  expect -c "$script"
  echo "Job completed on $i"
  echo "-----------------------------------"
}
export -f run_one

cat "$file" | parallel -j100 run_one '2>&1' >"$log2"

Или:

[compute $script]
export script

cat "$file" |
  parallel -j100 --tag 'i={} expect -c "$script" 2>&1' >"$log2"

решение2

Вы можете проверить, сколько заданий выполняется, и дождаться их завершения.

Вот пример сценария:

#!/bin/bash

i=0
while [[ $i -lt 50 ]]; do

    n=$(jobs | grep Running | wc -l)
    if [[ $n -ge 10 ]]; then
        echo "waiting for jobs to finish ($n running)"
        sleep 1
    else
        echo start next $i
        bash -c "sleep $(( $RANDOM % 3 )); echo $i finished" &
        let i+=1
    fi
done
wait

Чтобы ограничить число хостов одновременно до 100, можно использовать его следующим образом:

while IFS= read -r i
do
    n=$(jobs | grep Running | wc -l)
    if [[ $n -ge 100 ]]; then
        echo "waiting for jobs to finish ($n running)"
        sleep 1
    else
        ( export server_name=`echo $i`;echo "connecting to $i";expect -c "$script";echo "Job completed on $i";echo "-----------------------------------" ) >> "${log}_${i}" 2>&1 &
    fi
done < "$file"

решение3

Я обычно использую несколько иной подход, который не требует от вас отслеживания количества создаваемых вами подпроцессов, и всякий раз, когда очередь становится меньше вашего максимума, она заполняется.

max_jobs=100 # set queue size
while IFS= read -r i; do
  num_jobs=$(pgrep -c -P$$)
  if [[ $num_jobs -ge $max_jobs ]]; then
    wait -n $(pgrep -P$$) # Wait until a any subprocess terminates
  else
    <calling_awesome_script_here> &
  fi
done < "$file"

Связанный контент