シェルスクリプトで変数ループを使用する

シェルスクリプトで変数ループを使用する

キーを使用してサーバーにSSHを接続し、そこから多くのコンテンツを生成する次のスクリプトがあります。

#!/usr/bin/env bash

ssh -i mykey.pem myuser@SERVER_IP << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH

(私はこれを実行するために使用しましたsh scriptname.sh

別のサーバーで同じことをしたいので、2つの異なるファイル(ip_1およびip_2)を使用してSSHを介して2つの異なるサーバー(および)に接続する必要があります。.pemmykey1.pemmykey2.pem

これまで、私は次のようにIPを繰り返す方法を知っています。

#!/usr/bin/env bash

ip_list="ip_1 ip_2"

for ip in $ip_list; do
ssh -i mykey.pem myuser@$ip << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done

しかし、今私は正しいpemファイルを得るために繰り返したいと思います。この目標をどのように達成できますか?たぶん別のリストがありますか?誰かが私にエレガントなソリューションを提供できますか?

  • ip_1使用すべきmykey1.pem
  • ip_2使用すべきmykey2.pem

事前にありがとう

答え1

bashを使用しているので、次のものを使用できます。連想配列:

#!/usr/bin/env bash

declare -A ip_list=(["ip_1"]="mykey1.pem" ["ip_2"]="mykey2.pem")

for ip in "${!ip_list[@]}"; do
  ssh -i  "${ip_list[$ip]}" myuser@"$ip" << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done

ip_1通常のインデックス配列とは異なり、連想配列は特定の順序で保存されないため、以前に処理されるという保証はありませんip_2


もしあなたなら必要単純な POSIX 互換シェルを使用するには、1 行に 1 つずつ ip ファイルとキーファイルを含むファイルを作成します。

$ cat iplist.txt
ip1 mykey1.pem
ip2 mykey2.pem

次に、次のスクリプトを使用します。

#!/bin/sh

while read -r ip key; do
    ssh -i "$key" myuser@"$ip" << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH
done 

そして実行してください:

sh /path/to/script <  /path/to/iplist.txt

しかし、その道に行くとスティーブンの方法より良い。

答え2

1つの方法はwhile IFS=, read -rcsv hereドキュメントでループを使用することです。

#! /bin/sh -
while IFS=, read <&3 -r ip key; do
  ssh -i "$key" "$ip" << ENDSSH
  ...
ENDSSH
done 3<< ENDCSV
10.0.0.1,p1.pem
10.0.0.2,p2.pem
ENDCSV

その後、ユーザーにbashをインストールするように要求する必要さえありません。移植性が問題にならない場合は、複数のzsh変数のループをサポートする代替手段を使用できます。

#! /usr/bin/env zsh
for ip key (
  10.0.0.1 p1.pem
  10.0.0.2 p2.pem
) ssh -i $key $ip << ENDSSH
  ...
ENDSSH

答え3

set元のスクリプトは組み込み機能を使用して移植性をさらに向上させ、IPとキーをコロンで区切られた1つの文字列にまとめることができます。後でプレフィックスとサフィックスの削除を使用してそのアイテムを抽出できます。

#!/usr/bin/env bash

# Set positional parameters
# Example ip addresses
set -- 192.168.0.1:mykey1 192.168.1.1:mykey2

# iterating without specifying 'in' assumes positiona parameters
for host; do
    ssh -i ${host##*:}.pem myuser@${host%%:*} << 'ENDSSH'
[A LOT OF STUFF]
ENDSSH

done

関連情報