Exécuter plusieurs fonctions bash en arrière-plan et attendre leur retour

14

Il s'agit d'un simple script qui exécute la nvidia-smicommande sur plusieurs hôtes et enregistre sa sortie dans un fichier commun. Le but ici est de le faire fonctionner de manière asynchrone .

La &fin de l' process_host()appel de fonction est-elle suffisante? Mon script est-il correct?

#!/bin/bash

HOSTS=(host1 host2 host3)
OUTPUT_FILE=nvidia_smi.txt

rm $OUTPUT_FILE

process_host() {
    host=$1
    echo "Processing" $host
    output=`ssh ${host} nvidia-smi`
    echo ${host} >> $OUTPUT_FILE
    echo "$output" >> $OUTPUT_FILE
}

for host in ${HOSTS[@]}; do
    process_host ${host} &
done;

wait
cat $OUTPUT_FILE
syntagme
la source

Réponses:

13

Oui, mais votre sortie peut être tronquée. Il est préférable que la fonction écrive sa sortie dans un fichier spécifique en fonction du nom d'hôte, puis laisse le script principal concaténer le résultat (et nettoyer).

En outre, vous devez citer deux fois vos variables. Copiez et collez le script dans ShellCheck .

Peut-être quelque chose comme ça:

#!/bin/bash

hosts=( host1 host2 host3 )
outfile="nvidia_smi.txt"

rm -f "$outfile"

function process_host {
    local host="$1"
    local hostout="$host.out"
    printf "Processing host '%s'\n" "$host"
    echo "$host" >"$hostout"
    ssh "$host" nvidia-smi >>"$hostout"
}

for host in "${hosts[@]}"; do
    process_host "$host" &
done

wait

for host in "${hosts[@]}"; do
    hostout="$host.out"
    cat "$hostout"
    rm -f "$hostout"
done >"$outfile"

cat "$outfile"

La dernière boucle peut être remplacée par

cat "${hosts[@]/%/.out}" >"$outfile"
rm -f "${hosts[@]/%/.out}"
Kusalananda
la source
J'obtiens exactement la sortie que je veux obtenir, qu'est-ce qui pourrait mal tourner ici?
syntagma
2
@ ΔλЛ Si, par exemple, le premier hôte tarde à répondre, Processing host1sera suivi de Processing host2et la sortie de host2plutôt que la sortie de host1.
Kusalananda