SSH を介した for ループに 2 つの配列を入れ子にすると、接続されたユーザーは望ましくない順番になります。

SSH を介した for ループに 2 つの配列を入れ子にすると、接続されたユーザーは望ましくない順番になります。

3つのノードの一部のファイルを更新しようとしています。各接続を特定のユーザーパスにバインドする。私はこれに慣れていないので、for looprootとして接続するために使用した拡張を次に拡張しました。nested for loop 2つの異なる配列があります。

次のスクリプトもちろん、すべての接続で3つのユーザーパスをすべて試してください。。私はarraywithだけを使って試した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

おすすめ記事