EC2を複数台立ち上げた後、全てのEC2にSSH接続するためのTeraTermマクロファイルを作成するShellスクリプト

負荷試験を実施するために同じ構成のEC2を15台立ち上げてTeratermでSSH接続負荷試験を実施していたのですが、コスト削減のために**EIPを使用せずに負荷試験を実施しないときは停止する**ことにしました。
そうするともちろん**EC2を起動するたびに接続先のIPが変更される**ため、**毎回15台のIPをTeratermに入力**しなければいけません。

というわけで、**EC2を複数台立ち上げた後、接続先のIPを取得し、立ち上げた全てのEC2にSSH接続を行うTeratermマクロファイルを作成する**Shellスクリプトを作ることにしました。

## 事前準備

起動したいEC2のタグに

| NAME | VALUE|
|:-----------|:------------|
| ttl       | true        |
を登録しておきます。

## 本題
### Shellスクリプト
`※使用する際は
<profile>→AWS-CLIのプロファイル名、
<keypath>→接続に使うSSHKeyのフルパス
に置き換えてください。`

```shell
# aws cliのプロファイル
AWS_PROFILE_NAME=<profile>
# リージョン
REGION=ap-northeast-1

# 起動するEC2インスタンスリストを取得
INSTANCES_ID_LIST=$(
    aws ec2 describe-instances \
        --region $REGION \
        --profile $AWS_PROFILE_NAME \
        --output text \
        --filters "Name=tag:ttl,Values=true" \
        --query 'Reservations[*].Instances[*].InstanceId' |
        sed -e "s/[\r\n]\+//g"
)

# EC2インスタンスを起動する
INSTANCES=$(
    aws ec2 start-instances --instance-ids $INSTANCES_ID_LIST \
        --region $REGION \
        --profile $AWS_PROFILE_NAME \
        --output text &&
        aws ec2 wait instance-running --instance-ids $INSTANCES_ID_LIST \
            --region $REGION \
            --profile $AWS_PROFILE_NAME \
            --output text
)

# パブリックIPアドレスを取得
INSTANCES_IP=($(
    aws ec2 describe-instances --instance-ids $INSTANCES_ID_LIST \
        --region $REGION \
        --profile $AWS_PROFILE_NAME \
        --query 'Reservations[*].Instances[*].PublicIpAddress' \
        --output text |
        sed -e "s/[\r\n]\+//g"
))

# TeraTermマクロファイル（.ttl）を作成する
echo '' >loadtest-connecct.ttl | sed -e "s/[\r\n]\+//g" >loadtest-connecct.ttl
cat <<-EOS >>loadtest-connecct.ttl

        $(
    echo strdim ip ${#INSTANCES_IP[@]}
    for ((i = 0; i < ${#INSTANCES_IP[@]}; i++)); do
        echo "ip[$i] = '${INSTANCES_IP[i]}'"
    done
    echo for i 0 $((${#INSTANCES_IP[@]} - 1))
    echo username = "'ec2-user'"
    echo hostname = ip[i]
    echo keyfile = "'<keypath>'"

    echo msg = hostname
    echo strconcat msg "':22 /ssh /auth=publickey /nosecuritywarning /user='"
    echo strconcat msg username
    echo strconcat msg "' /keyfile='"
    echo strconcat msg keyfile
    echo connect msg
    echo unlink
    echo next
)

EOS

```

## やっていること
やっていることは冒頭で記述した通りです。

- タグにttl = trueが定義されているEC2インスタンスのリストを取得
- 取得したEC2インスタンスを全て起動
- 起動したインスタンスのパブリックIPを取得
- 取得したパブリックIPを使用してSSH接続を実施するTeraTermマクロファイルをヒアドキュメントで作成

## 動作確認
今回接続したいEC2はこちらです。
ttl1,ttl2,ttl3それぞれに**ttl = true**タグを定義しています。
![スクリーンショット 2020-10-09 163922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246580/1db933de-496c-6077-8077-61490d932c11.png)

shellを実行するとEC2が起動し、ttlファイルが作成されています。
![スクリーンショット 2020-10-09 164146.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246580/e7aaa976-5ffa-fdfe-e97b-214ff4bb6e52.png)

内容を見てみます。

### 生成されたttlファイルの内容
```ttl
strdim ip 3
ip[0] = '3.112.15.xxx'
ip[1] = '35.72.3.xxx'
ip[2] = '18.181.203.xxx'
for i 0 2
username = 'ec2-user'
hostname = ip[i]
keyfile = "'<keypath>'"
msg = hostname
strconcat msg ':22 /ssh /auth=publickey /nosecuritywarning /user='
strconcat msg username
strconcat msg "' /keyfile='"
strconcat msg keyfile
connect msg
unlink
next
```
起動したEC2のパブリックIP配列を作成した後、パブリックIP配列に対してループ処理を行い、SSH接続を試みています。
実際にTeraTermマクロを実行すると、起動したEC2台数分のTeraTermが立ち上がってSSH接続してくれます。

## 終わりに
このshellスクリプトを応用すれば**複数台サーバーに対して同じファイルを一括でSCP送信**するスクリプトなどを簡単に作れると思います。
是非カスタマイズして便利なTeraTermライフを送ると同時に、記事などでアウトプットシェアしてみんなで幸せになりましょう。