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


14

これは、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

回答:


13

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

また、変数を二重引用符で囲む必要があります。スクリプトをコピーして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}"

取得したい出力を正確に取得できますが、ここで何が間違っているのでしょうか?
シンタグマ

2
@ΔλЛたとえば、最初のホストの応答が遅い場合は、からの出力ではなくからの出力Processing host1が続きます。Processing host2host2host1
クサラナナンダ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.