запустить bash для l oop параллельно - PullRequest
2 голосов
/ 25 марта 2020

У меня есть этот скрипт, который выполняет поиск учетных данных для каждого хоста в локальной системе хранилищ, а затем запускает для него ansible -плейбук.

#!/bin/bash

for host in `cat ~/.ansible/hosts`
  do
    SECRET=`/opt/vault/bin/get-admin-credential --tag=$host`
    HOST=`echo $SECRET | cut -d ';' -f1`
    LOGIN=`echo $SECRET | cut -d ';' -f2`
    DOMAIN=`echo $SECRET | cut -d ';' -f3`
    PWD=`echo $SECRET | cut -d ';' -f4`

    if [ -z "$DOMAIN" ]; then
      ansible-playbook -i ~/.ansible/hosts ~/.ansible/windows.yml -e "ansible_host=$HOST ansible_user=$LOGIN ansible_password=$PWD" --limit $host
    else
      ansible-playbook -i ~/.ansible/hosts ~/.ansible/windows.yml -e "ansible_host=$HOST ansible_user=$LOGIN@$DOMAIN ansible_password=$PWD" --limit $host
    fi
  done

Это повторяется на каждом хосте последовательно, я пробовал что-то с GNU parallel, но не смог сделать то, что я хочу, запустив для l oop с 5 параллельно.

Кто-нибудь направит меня вправо направление

Ответы [ 2 ]

2 голосов
/ 25 марта 2020

У меня нет "ansibles" или "хранилищ" , так что это полностью не проверено, но может приблизить вас:

doit(){
   host="$1"

   SECRET=$(/opt/vault/bin/get-admin-credential --tag=$host)
   HOST=$(echo $SECRET | cut -d ';' -f1)
   LOGIN=$(echo $SECRET | cut -d ';' -f2)
   DOMAIN=$(echo $SECRET | cut -d ';' -f3)
   PWD=$(echo $SECRET | cut -d ';' -f4)

   if [ -z "$DOMAIN" ]; then
      ansible-playbook -i ~/.ansible/hosts ~/.ansible/windows.yml -e "ansible_host=$HOST ansible_user=$LOGIN ansible_password=$PWD" --limit $host
   else
      ansible-playbook -i ~/.ansible/hosts ~/.ansible/windows.yml -e "ansible_host=$HOST ansible_user=$LOGIN@$DOMAIN ansible_password=$PWD" --limit $host
   fi
}

# Export doit function to subshells created by GNU Parallel
export -f doit

parallel -a ~/.ansible/hosts doit

Стилистически Есть несколько улучшений. Во-первых, переменные оболочки, состоящие из букв верхнего регистра, зарезервированы, поэтому вам не следует использовать HOST, DOMAIN et c. Кроме того, вы, вероятно, можете упростить все эти неприглядные сокращения и эхо, чтобы извлечь переменные из СЕКРЕТА, используя IFS=';' и read, например:

SECRET=$(/opt/vault/bin/get-admin-credential --tag=$host)
IFS=';' read host login domain pwd <<< "$SECRET"

Итак, мой лучший и окончательный ответ: :

doit(){
   host="$1"

   secret=$(/opt/vault/bin/get-admin-credential --tag=$host)
   IFS=';' read host login domain pwd <<< "$secret"

   if [ -z "$domain" ]; then
      ansible-playbook -i ~/.ansible/hosts ~/.ansible/windows.yml -e "ansible_host=$host ansible_user=$login ansible_password=$pwd" --limit $host
   else
      ansible-playbook -i ~/.ansible/hosts ~/.ansible/windows.yml -e "ansible_host=$host ansible_user=$login@$domain ansible_password=$pwd" --limit $host
   fi
}

# Export doit function to subshells created by GNU Parallel
export -f doit

parallel -a ~/.ansible/hosts doit
1 голос
/ 25 марта 2020

Вам просто нужно запустить ansible-playbook в фоновом режиме, используя терминатор команды &. Обратите внимание, что все l oop можно упростить и улучшить.

run_playbook () {
  ansible-playbook -i ~/.ansible/hosts \
                   -e "ansible_host=$2 ansible_login=$3 ansible_password=$4" \
                   ~/.ansible/windows.yml --limit "$1"
}

while IFS= read -r host; do
    secret=$(/opt/vault/bin/get-admin-credential --tag="$host")
    IFS=";" read -r shost slogin sdomain spasswd _ <<< "$secret"
    if [[ -n $sdomain ]]; then
      login="$slogin@$sdomain"
    fi
    run_playbook "$host" "$shost" "$login" "$password" &
done < ~/.ansible/hosts
...