Uruchamianie wielu funkcji bash w tle i czekanie na ich powrót

14

Jest to prosty skrypt, który uruchamia nvidia-smipolecenie na wielu hostach i zapisuje dane wyjściowe we wspólnym pliku. Celem jest, aby działał asynchronicznie .

Czy &na końcu process_host()wywołania funkcji jest wystarczające? Czy mój skrypt jest poprawny?

#!/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
syntagma
źródło

Odpowiedzi:

13

Tak, ale Twoje wyniki mogą być zniekształcone. Lepiej jest, aby funkcja zapisała dane wyjściowe do określonego pliku w zależności od nazwy hosta, a następnie pozwoliła skryptowi głównemu połączyć wynik (i wyczyścić).

Powinieneś także podwójnie podać swoje zmienne. Skopiuj i wklej skrypt do ShellCheck .

Może coś takiego:

#!/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"

Ostatnia pętla może zostać zastąpiona przez

cat "${hosts[@]/%/.out}" >"$outfile"
rm -f "${hosts[@]/%/.out}"
Kusalananda
źródło
Dostaję dokładnie taki wynik, jaki chcę uzyskać, co może tu pójść nie tak?
syntagma
2
@ ΔλЛ Jeśli, na przykład, pierwszy host reaguje wolno, Processing host1po nim następuje Processing host2wyjście, host2a nie wyjście z host1.
Kusalananda