web-dev-qa-db-ja.com

バックグラウンドで複数のbash関数を実行し、それらが戻るまで待機する

これは、複数のホストで_nvidia-smi_コマンドを実行し、その出力を共通ファイルに保存する単純なスクリプトです。ここでの目標は、それを実行することです非同期

process_Host()関数呼び出しの最後の_&_で十分ですか?私のスクリプトは正しいですか?

_#!/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
_
14
syntagma

はい。ただし、出力が文字化けする場合があります。ホスト名に応じて、関数に出力を特定のファイルに書き込んでから、メインスクリプトで結果を連結(クリーンアップ)することをお勧めします。

また、変数を二重引用符で囲む必要があります。スクリプトをコピーして ShellCheck に貼り付けます。

多分このようなもの:

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

最後のループは、

cat "${hosts[@]/%/.out}" >"$outfile"
rm -f "${hosts[@]/%/.out}"
13
Kusalananda