3つのノードの一部のファイルを更新しようとしています。各接続を特定のユーザーパスにバインドする。私はこれに慣れていないので、for loop
rootとして接続するために使用した拡張を次に拡張しました。nested for loop
2つの異なる配列があります。。
次のスクリプトもちろん、すべての接続で3つのユーザーパスをすべて試してください。。私はarray
withだけを使って試したips
後、各ユーザーが3つのノードすべてに接続しようとしました。
#!/bin/bash
EXTENSIONS='/home/bi/.local/share/gnome-shell/extensions'
NODE_SRVS=(
'[email protected]'
'[email protected]'
'[email protected]'
)
NODE_USERS=(
'mf'
'lf'
'qf'
)
echo -e "sync my extensions to my nodes \c"; read
for i in ${NODE_SRVS[@]}; do
for u in ${NODE_USERS[@]}; do
rsync -rt --delete --info=progress2,stats2 \
-e ssh -tt \
$EXTENSIONS/ \
$i:/home/$u/.local/share/gnome-shell/extensions/
done
done
配列配列を制限する方法はありますか?最初のアレイ接続は、最初のアレイのユーザー名に固有のものです。、など?
そうでなければ何が正しいか各接続をそのユーザーパスにのみ一致させるループ構成はありますか?
答え1
うん、繰り返して索引彼らではなく配列のもの価値。しかし、両方の配列はインデックスを共有するので、イテレータ変数は1つだけ必要です($i
下)。
bash
配列は0から始まり、"${#arrayname[@]}"
-を使用して要素数を取得できるため、0からそれより小さい1まで繰り返す必要があります。 3つの要素を含む配列はインデックス0、1、2を持ちます。配列の作成時にインデックスに間隔がないとします。 「間隔」とは、数値インデックスが「欠落している」という意味です(配列に挿入されていないか、挿入後に一定時間が経過すると削除されます)。たとえば、配列にはインデックス1、3、5があります。 2と4がありません。
例えば
i=0
while [ "$i" -lt "${#NODE_SRVS[@]}" ] ; do
# setting $h and $u isn't strictly necessary but makes the code
# easier to read, at little performance cost.
h="${NODE_SRVS[$i]}"
u="${NODE_USERS[$i]}"
rsync -rt --delete --info=progress2,stats2 \
-e ssh -tt \
"$EXTENSIONS/" \
"$h:/home/$u/.local/share/gnome-shell/extensions/
let i+=1
done
すべてのインデックスリストを取得するためにも使用できます"${!arrayname[@]}"
。スペースを無視し、存在するインデックスのみをリストします。以下を使用して繰り返すことができますfor
。
for i in "${!NODE_SRVS[@]}" ; do
h=....
u=...
rsync ...
done
これはインデックス配列には便利ですが(間隔がある可能性があるため)、関連配列には特に便利です。これは次の選択肢につながります。たとえば、ユーザー名は次の連想配列(「ハッシュ」とも呼ばれます)を使用します。キー(インデックス)とホスト名/ IPアドレスは値です(このような単純な場合は、IPアドレスをキーとして、ユーザー名を値として使用することもできます)。
declare -A NODES
NODES=([mf]=192.168.122.60)
NODES+=([lf]=192.168.122.92)
NODES+=([qf]=192.168.122.93)
EXTENSIONS="something"
for u in "${!NODES[@]}"; do
rsync -rt --delete --info=progress2,stats2 \
-e ssh -tt \
"$EXTENSIONS/" \
"$u@${NODES[$u]}:/home/$u/.local/share/gnome-shell/extensions/"
done
echo
先頭に行がある出力の例rsync
:
rsync -rt --delete --info=progress2,stats2 -e ssh -tt something/ [email protected]:/home/qf/.local/share/gnome-shell/extensions/
rsync -rt --delete --info=progress2,stats2 -e ssh -tt something/ [email protected]:/home/lf/.local/share/gnome-shell/extensions/
rsync -rt --delete --info=progress2,stats2 -e ssh -tt something/ [email protected]:/home/mf/.local/share/gnome-shell/extensions/
しかし、Bashの連想配列は本質的に順序がない。つまり、事実上、ランダムな順序でキーを繰り返すという意味です。時にはこれが重要な場合もありますが、そうでない場合もあります。重要でない場合は、連想配列を使用するのが便利です。本当に重要な場合は、上記の最初の例のように2つのインデックス配列を使用してください。
ハッシュの利便性が欲しいが、生成された順序で配列を処理する必要がありますが、インデックス配列を使用し、ハッシュのキーを配列の値にする必要がある場合は、ハッシュを使用します。インデックス配列を繰り返して、挿入順にハッシュのキー名を取得します。例えば
...
ORDER=(mf lf qf)
for u in "${ORDER[@]}"; do
rsync -rt --delete --info=progress2,stats2 \
-e ssh -tt \
"$EXTENSIONS/" \
"$u@${NODES[$u]}:/home/$u/.local/share/gnome-shell/extensions/"
done
答え2
配列の要素全体の組み合わせではなく、2つの配列のペアを構成する要素を繰り返すには、1つの配列を繰り返し、各反復ごとに別の配列から次の要素を取得します。
shift
要素を削除するために使用できる場所引数リストに2番目のリストが残っていると、構文の面で簡単になります。
#!/bin/bash
list1=( element1 element2 element3 )
list2=( thing1 thing2 thing3 )
# Assign the second list to
# the list of positional parameters:
set -- "${list2[@]}"
# Loop over the first list and pull out
# the next element of the second list
# in each iteration, to pair up the elements:
for element in "${list1[@]}"; do
printf 'Pair: %s %s\n' "$element" "$1"
shift
done
出力:
Pair: element1 thing1
Pair: element2 thing2
Pair: element3 thing3
これを特定の例に適用します。
#!/bin/bash
node_servers=(
'192.168.122.60'
'192.168.122.92'
'192.168.122.93'
)
node_users=(
'mf'
'lf'
'qf'
)
extension_path=.local/share/gnome-shell/extensions
set -- "${node_users[@]}"
for server in "${node_servers[@]}"; do
rsync -ai --delete ~bi/"$extension_path"/ "$1@$server:$extension_path"
shift
done
ただし、元のサーバーリストにはすでにユーザー名が含まれているため、2番目のリストは必要ありません。
#!/bin/bash
node_servers=(
'[email protected]'
'[email protected]'
'[email protected]'
)
extension_path=.local/share/gnome-shell/extensions
for server in "${node_servers[@]}"; do
rsync -ai --delete ~bi/"$extension_path"/ "$server:$extension_path"
done
上記の2つのコードスニペットは、現在のディレクトリが接続しようとしているユーザーのホームディレクトリであると想定しています。
答え3
私が感謝しているすべての提案を考えてみると、適用するより簡単な解決策は、次のように配列インデックスを使用することです。
#!/bin/bash
EXTENSIONS='/home/bi/.local/share/gnome-shell/extensions'
IPS=(
'192.168.122.60'
'192.168.122.92'
'192.168.122.93'
)
USERS=(
'mf'
'lf'
'qf'
)
echo -e "sync my extensions to my nodes \c"; read
for i in ${!IPS[*]}; do
rsync -rt --delete --info=progress2,stats2 \
-e ssh -tt \
$EXTENSIONS/ \
${USERS[$i]}@${IPS[$i]}:/home/${USERS[$i]}/.local/share/gnome-shell/extensions/
done