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
答え1
はい、スクリプトは正しいですが、出力が壊れているか、順序が間違っている可能性があります。関数がホスト名に基づいて特定のファイルに出力を書き込んでから、基本スクリプトに結果をリンクしてクリーンアップさせることをお勧めします。
また、変数を二重引用符で囲む必要があります。スクリプトをコピーして貼り付けます。住宅検査。
たぶん、次のようなものがあります。
#!/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}"
2016年と2021年の以前の答えを見ると、今日は次のようなコードを書くことができます。
#!/bin/sh
set -- host1 host2 host3
outfile=nvidia_smi.txt
for host do
ssh "$host" nvidia-smi >"$outfile-$host" &
done
echo 'Commands submitted, now waiting...'
wait
for host do
cat "$outfile-$host"
rm -f "$outfile-$host"
done >"$outfile"
echo 'Done.'
実際には名前付き配列は必要ないので、これは短いです。したがって、代わり/bin/sh
に実行できますbash
。代わりに、接続するホストのリストが場所パラメータのリストに保存されます。また、ループ内の情報出力とシェル関数(実際に多くのことはしません)を削除しました。
使用可能なファイル名を構成するのではなく、適切な一時ファイルを使用するバリアント:
#!/bin/sh
set -- host1 host2 host3
outfile=nvidia_smi.txt
for host do
tmpfile=$(mktemp)
ssh "$host" nvidia-smi >"$tmpfile" &
set -- "$@" "$tmpfile"
shift
done
echo 'Commands submitted, now waiting...'
wait
# Concatenate the output files and delete them.
cat -- "$@" >"$outfile"
rm -f -- "$@"
echo 'Done.'
これは、場所パラメーターのホスト名をそのホストへの出力を含む一時ファイルのパス名に置き換えます。