Executando várias funções bash em segundo plano e aguardando até que retornem

14

Este é um script simples que executa o nvidia-smicomando em vários hosts e salva sua saída em um arquivo comum. O objetivo aqui é fazer com que seja executado de forma assíncrona .

É &no final da process_host()chamada de função é suficiente? Meu script está correto?

#!/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
sintagma
fonte

Respostas:

13

Sim, mas sua saída pode estar distorcida. É melhor fazer com que a função grave sua saída em um arquivo específico, dependendo do nome do host, e deixe o script principal concatenar o resultado (e limpar).

Além disso, você deve citar duas vezes suas variáveis. Copie e cole o script no ShellCheck .

Talvez algo parecido com isto:

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

O último loop pode ser substituído por

cat "${hosts[@]/%/.out}" >"$outfile"
rm -f "${hosts[@]/%/.out}"
Kusalananda
fonte
Recebo exatamente a saída que quero obter, o que poderia dar errado aqui?
Syntagma
2
@ ΔλЛ Se, por exemplo, o primeiro host demorar a responder, Processing host1será seguido pela Processing host2saída host2e não pela saída host1.
Kusalananda