AWS CLI を使ったEC2インスタンスのステータス確認と起動停止をするシェル実装例


## EC2のNameタグからインスタンスIDを確認

```
HOST="server-1"
INSTANCE_ID=`aws ec2 describe-tags \
    --filters \
      "Name=resource-type,Values=instance" \
      "Name=key,Values=Name" \
      "Name=tag-key,Values=Name" \
      "Name=tag-value,Values=${HOST}" \
    --query "Tags[*].{InstanceId:ResourceId}" \
    --output text`

echo "hostname:    ${HOST}"
echo "instance-id: ${INSTANCE_ID}"
```

## EC2インスタンスステータス確認（describe-instance-status）

下記でAWSコンソールで参照できるステータスを確認可能。
但しインスタンス停止時はアウトプットはNullになるので停止時もステータスを取りたければ describe-instances の方を使った方がよい。

```
aws ec2 describe-instance-status --instance-ids ${INSTANCE_ID} --output table
```

結果はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551087/95bbab31-c97b-03b5-2692-dbff46ddc775.png)

このあたりを参考にqueryで絞り込み
https://qiita.com/kkino1985/items/417483a91b5682400150

```
$ aws ec2 describe-instance-status --instance-ids ${INSTANCE_ID} \
    --query "[InstanceStatuses[*].{InstanceId:InstanceId}, \
    InstanceStatuses[*].InstanceState[].{InstanceState:Name}, \
    InstanceStatuses[*].InstanceStatus[].{InstanceStatus:Status}, \
    InstanceStatuses[*].SystemStatus[].{SystemStatus:Status}]" \
    --output json

[
    [
        {
            "InstanceId": "i-99a9aa9a99999a00a"
        }
    ],
    [
        {
            "InstanceState": "running"
        }
    ],
    [
        {
            "InstanceStatus": "ok"
        }
    ],
    [
        {
            "SystemStatus": "ok"
        }
    ]
]
```

## EC2インスタンスステータス確認（describe-instances）

結果は running または stopped で返されるので結果を変数に代入してif文で分岐

```
INSTANCE_STATE=`aws ec2 describe-instances --instance-ids ${INSTANCE_ID} \
    --query "Reservations[].Instances[].State.Name" --output text`

if [ ${INSTANCE_STATE} == "running" ]; then
    echo "Instance ${INSTANCE_ID} is running state" 
elif [ ${INSTANCE_STATE} == "stopped" ]; then
    echo "Instance ${INSTANCE_ID} is stopped state" 
fi
```

## EC2インスタンス停止

停止コマンド実行の上、10秒間隔で最大30回停止ステータスになった事を確認するスクリプト。
${INSTANCE_ID} は事前に取得されている事が前提。

```
MAX_RETRY_NUM=30
CHECK_INTERVAL=10

aws ec2 stop-instances --instance-ids=${INSTANCE_ID}
if [ $? -ne 0 ]; then
    echo "`date` Executing stop nstance ${INSTANCE_ID} (${HOST}) was failed."
    exit 2
fi

RTN=0
i=0
while true
do
    sleep ${CHECK_INTERVAL}
    i=`expr $i + 1`
    INSTANCE_STATE=`aws ec2 describe-instances  --instance-ids ${INSTANCE_ID} --query "Reservations[].Instances[].State.Name" --output text`
    if [ ${INSTANCE_STATE} == "stopped" ]; then
        RTN=0
        echo "Instance ${INSTANCE_ID} was stopped successfully."
        break
    fi
    if [ ${i} -ge ${MAX_RETRY_NUM} ]; then
        RTN=2
        echo "Stopping instance ${INSTANCE_ID} was failed."
        break
    fi
    echo "Waiting for stopped status"
done
echo ${RTN}
```

## EC2インスタンス起動

起動コマンド実行の上、10秒間隔で最大30回停止ステータスになった事を確認するスクリプト。
ステータスチェックはインスタンスの状態だけでなくステータスチェックが両方ともOKになっている事を確認して終了。
${INSTANCE_ID} は事前に取得されている事が前提。

```
MAX_RETRY_NUM=30
CHECK_INTERVAL=10

aws ec2 start-instances --instance-ids=${INSTANCE_ID} >> ${LOG} 2>&1
if [ $? -ne 0 ]; then
    echo "ERROR Executing start instance was failed."
    exit 2
fi

RTN=0
i=0
while true
do
    sleep ${INSTANCE_CHK_WAIT}
    i=`expr $i + 1`

    # Assign result to the positional parameters using "set --"
    set -- `aws ec2 describe-instance-status --instance-ids ${INSTANCE_ID} \
            --query "[InstanceStatuses[*].InstanceState[].{InstanceState:Name}, \
            InstanceStatuses[*].InstanceStatus[].{InstanceStatus:Status}, \
            InstanceStatuses[*].SystemStatus[].{SystemStatus:Status}]" \
            --output text`
    
    # Check if all status is ok
    if [ "$1" == "running" ] && [ "$2" == "ok" ] && [ "$3" == "ok" ] ; then
        RTN=0
        echo "Start instance ${INSTANCE_ID} was executed sucessfully."
        breadk
    fi
    
    # Error exit if retry count is exceeded
    if [ ${i} -ge ${INSTANCE_CHK_RETRY} ]; then
        RTN=2
        echo "Start instance ${INSTANCE_ID} was failed."
        breadk
    fi

    echo "Waiting for status check is ok"
done
echo ${RTN}
```