EC2の起動/停止/確認/ログインスクリプトのご紹介

記事タイトルとURLをコピーする

こんにちは。AWS CLIが好きな福島です。

はじめに

皆様は開発や検証で利用するEC2の起動/停止/確認/ログインはどのようにしていますでしょうか。

私は上記処理をスクリプトで行っているため、それをご紹介したいと思います。

実行環境

# uname -a
Linux LAPTOP-CNM26HN6 5.4.72-microsoft-standard-WSL2 #1 SMP Wed Oct 28 23:40:43 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
#

使い方

###################################################################
####
#### Usage : ec2-action.sh ${ACTION} ${OPTION}
####
###################################################################

case ${ACTION} in
    ssh )     : SSHアクション
    rdp )     : RDPアクション
    start )   : EC2を起動するアクション
    stop )    : EC2を停止するアクション
    status )  : EC2の状態を確認するアクション
    list  )   : EC2の一覧を表示するアクション

case ${OPTION} in
    -h ${1} ) : ホスト(EC2のNameタグ)を指定するオプション
    -u ${1} ) : OSユーザ名を指定するオプション
    -k ${1} ) : キーペアを指定するオプション
    -p ${1} ) : aws cliのプロファイル名を指定するオプション
    -a )      : EC2全台を対象とするで使えるオプション(start,stop,statusアクションで利用可)
    ※${1}には、任意の値を指定する。

オプションのデフォルトはスクリプトに定義している変数で設定可能です。

## オプションのデフォルト設定
KEY_DIR="[キーペアが保存されているディレクトリ]"
KEY="${KEY_DIR}/[キーペア名]"
OSUSER="[SSHのOSユーザー名]"
RDP_OSUSER="[RDPのOSユーザー名]"
HOST="[Nameタグ]"
PROFILE="[プロファイル名]"

使用例

前提

以下の変数を設定している前提で使用例を記載いたします。

## オプションのデフォルト設定
KEY_DIR="/mnt/c/Users/serverworker/Desktop/wsl-root/4_key-pea"
KEY="${KEY_DIR}/fk-test-key.pem"
OSUSER="ec2-user"
RDP_OSUSER="administrator"
HOST=""
PROFILE="kensho"

EC2の一覧

# ./ec2-action.sh list
=====================
NAME_TAG
=====================
fk-windows
fk-linux
#

EC2の状態確認

# ./ec2-action.sh -h fk-linux status
=====================  ============
NAME_TAG               STATUS
=====================  ============
fk-linux               stopped
#

EC2の起動

Nameタグを指定してEC2の起動

# ./ec2-action.sh -h fk-linux start
#

プロファイル名を指定して全EC2の起動

# ./ec2-action.sh -p kensho -a start
以下のEC2を [start] しますが、問題ないですか?(yes or no)
====================
対象EC2
====================
fk-windows
fk-linux
yes
#

EC2の停止

Nameタグを指定してEC2の停止

# ./ec2-action.sh -h fk-linux stop
#

全EC2の停止

# ./ec2-action.sh -a stop
以下のEC2を [stop] しますが、問題ないですか?(yes or no)
====================
対象EC2
====================
fk-windows
fk-linux
no
処理を中断しました。
#

EC2へSSH

※パブリックIPが付与されている前提です。(EIPは不要)

Nameタグを指定してEC2へアクセス

# ./ec2-action.sh -h fk-linux ssh
Last login: Sat Jan 28 23:58:26 2023 from m106073017192.v4.enabler.ne.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-88-0-59 ~]$

Nameタグ,ユーザー名,キーペアを指定してEC2へSSH

# ./ec2-action.sh -h fk-linux -u ec2-user -k fk-test-key.pem ssh
Last login: Sat Jan 28 23:58:26 2023 from m106073017192.v4.enabler.ne.jp

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-10-88-0-59 ~]$

EC2へRDP

※パブリックIPが付与されている前提です。(EIPは不要)

Nameタグ,ユーザー名,キーペアを指定してEC2へRDP

# ./ec2-action.sh -h fk-windows -u administrator -k fk-test-key.pem rdp
#

※RDPの処理はWindowsのコマンドを利用しています。

        /mnt/c/WINDOWS/system32/cmdkey.exe /generic:TERMSRV/${PUBLIC_IP} /user:${OSUSER} /pass:${WIN_PASS} >> /dev/null 2>&1
        /mnt/c/WINDOWS/system32/mstsc.exe /v:${PUBLIC_IP} &
            sleep 3
        cmdkey.exe /delete:TERMSRV/${PUBLIC_IP} >> /dev/null 2>&1

スクリプト(ec2-action.sh)の中身

 #!/bin/bash

TMP="/tmp/ec2-action.tmp"

## オプションのデフォルト設定
KEY_DIR="/mnt/c/Users/serverworker/Desktop/wsl-root/4_key-pea"
KEY="${KEY_DIR}/fk-test-key.pem"
OSUSER="ec2-user"
RDP_OSUSER="administrator"
HOST=""
PROFILE="kensho"

## スクリプトの引数チェック関数
function option_check {
    case ${1} in

        ssh | rdp )
            if [[ -z ${OSUSER} ]] || [[ -z ${KEY} ]] || [[ -z ${HOST} ]] ; then
                echo "-hを指定する必要があります。"
                echo "また、-kでキーペアを指定、-uでOSユーザを指定できます。"
                exit 9
            fi;;

        start | stop | status )
            if [[ -z ${HOST} ]] && [[ -z ${MODE} ]] ; then
                echo "-aまたは-hがオプションが必要になります。"
                exit 9
            fi;;

        * )
            if [[ -z ${2} ]] ; then
                echo "${1}に値を設定してください。"
                exit 9
            fi;;
    esac
}

## EC2にSSHまたはRDPする関数
function os_access {
    PUBLIC_IP=$(\
        aws ec2 describe-instances \
        --filters "Name=tag-key,Values=Name" "Name=tag-value,Values=${HOST}" \
        --query "Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddresses[].Association[].PublicIp" \
        --output text\
        --profile ${PROFILE})

    INSTANCE_ID=$(\
        aws ec2 describe-instances \
        --filters "Name=tag-key,Values=Name" "Name=tag-value,Values=${HOST}" \
        --query "Reservations[].Instances[].InstanceId" \
        --output text \
        --profile ${PROFILE})

    WIN_PASS=$(aws ec2 get-password-data \
        --instance-id ${INSTANCE_ID} \
        --priv-launch-key ${KEY} \
        --query "PasswordData" \
        --output text \
        --profile ${PROFILE})

    if [[ ${ACTION} == ssh ]] ; then
        ssh -i ${KEY} -l ${OSUSER} ${PUBLIC_IP}
    elif [[ ${ACTION} == rdp ]] ; then
        OSUSER=${RDP_OSUSER}
        /mnt/c/WINDOWS/system32/cmdkey.exe /generic:TERMSRV/${PUBLIC_IP} /user:${OSUSER} /pass:${WIN_PASS} >> /dev/null 2>&1
        /mnt/c/WINDOWS/system32/mstsc.exe /v:${PUBLIC_IP} &
            sleep 3
        cmdkey.exe /delete:TERMSRV/${PUBLIC_IP} >> /dev/null 2>&1
    fi
}

## EC2を起動または停止する関数
function ec2_action {
    INSTANCE_ID=$(\
        aws ec2 describe-instances \
        --filters "Name=tag-key,Values=Name" "Name=tag-value,Values=${HOST}"  \
        --query "Reservations[].Instances[].InstanceId" \
        --output text \
        --profile ${PROFILE})
    aws ec2 ${ACTION}-instances --instance-ids ${INSTANCE_ID} >> /dev/null 2>&1
}

## EC2の状態を確認する関数
function ec2_status {
    STATUS=$(\
        aws ec2 describe-instances \
        --filters "Name=tag-key,Values=Name" "Name=tag-value,Values=${HOST}" \
        --query "Reservations[].Instances[].State[].Name[]"\
        --output text \
        --profile ${PROFILE})
    if  [[ -z ${HOST} ]] ; then
        HOST="Nameタグは存在しません。"
        STATUS=""
    elif [[ -z ${STATUS} ]] ; then
        STATUS="左記のNameタグは存在しません。"
    fi
    echo "${HOST} ${STATUS}"
}

## EC2の一覧を表示する関数
function ec2_list {
    aws ec2 describe-instances \
    --query "Reservations[].Instances[].Tags[?Key=='Name'].Value" \
    --output text \
    --profile ${PROFILE}
}

## スクリプトの引数を変数に入れる処理
while :
do
    case ${1} in
        -h)
            option_check ${1} ${2}
            HOST=${2}
            ec2_list > ${TMP}
            if [[ 0 -eq $(echo ${HOST} | grep \, | wc -l) ]] && [[ 0 -eq $(grep ^${HOST}$ ${TMP} | wc -l) ]] ; then
                echo "${HOST}というNameタグは、存在しません。"
                exit 9
            else
                for H in $(echo ${HOST} | tr "," " ")
                do
                    if [[ 0 -eq $(grep "^${H}$" ${TMP} | wc -l) ]] ; then
                        echo "${H}というNameタグは、存在しません。"
                        exit 9
                    fi
                done
            fi
            rm ${TMP}
            shift 2;;

        -u)
            option_check ${1} ${2}
            OSUSER=${2}
            shift 2;;

        -k)
            option_check ${1} ${2}
            KEY="${KEY_DIR}/${2}"
            shift 2;;

        -p)
            option_check ${1} ${2}
            PROFILE=${2}
            shift 2;;

        -a)
            MODE=all
            shift 1;;

        ssh | rdp | start | stop | status | list | pw)
            if [[ -z ${FLAG} ]] ; then
                ACTION=${1}
                FLAG=0
            else
                ACTION_TMP=${1}
                echo "アクション([${ACTION}],[${ACTION_TMP}])が2つ指定されています。"
                exit 9
            fi
            shift ;;

         *)
            if [[ ! -z ${ACTION} ]] ; then
                break
            else
                cat << EOF

###################################################################
####
#### WARN  : EC2のNameタグが付与されていることを前提にしてます。
####
###################################################################

###################################################################
####
#### Usage : ec2-action.sh \${ACTION} \${OPTION}
####
###################################################################

case \${ACTION} in
    ssh )     : SSHアクション
    rdp )     : RDPアクション
    start )   : EC2を起動するアクション
    stop )    : EC2を停止するアクション
    status )  : EC2の状態を確認するアクション
    list  )   : EC2の一覧を表示するアクション

case \${OPTION} in
    -h \${1} ) : ホスト(EC2のNameタグ)を指定するオプション
    -u \${1} ) : OSユーザ名を指定するオプション
    -k \${1} ) : キーペアを指定するオプション
    -p \${1} ) : aws cliのプロファイル名を指定するオプション
    -a )      : EC2全台を対象とするで使えるオプション(start,stop,statusアクションで利用可)
    ※\${1}には、任意の値を指定する。

###################################################################
####
#### Example Usage
####
###################################################################

 ## EC2の一覧を出力
    ec2-action.sh list

 ## aws cliのプロファイルを指定して、EC2の一覧を出力
    ec2-action.sh -a status

 ## 指定したEC2を起動
    ec2-action.sh -h host -u ec2-user -k test-key start

 ## 全てのEC2の状態を確認
    ec2-action.sh -a status

 ## 指定したEC2にSSH接続
    ec2-action.sh -h host -u ec2-user -k test-key ssh

EOF
                break
            fi;;
    esac
done

## スクリプトの引数のアクションに応じた処理
case ${ACTION} in

    ssh | rdp)
        option_check ${ACTION}
        os_access;;

    start | stop)
        option_check ${ACTION}
    if [[ -z ${MODE} ]] ; then
        ec2_action
    else
        echo "以下のEC2を [${ACTION}] しますが、問題ないですか?(yes or no)"
        HOST=$(ec2_list | sed  '/^$/d' | tr "\n" "," | sed 's/,$//g')
        cat << EOF
====================
対象EC2
====================
$(echo ${HOST} | tr "," "\n")
EOF
        read ANSWER
        if [[ ${ANSWER} != yes ]] ; then
            echo "処理を中断しました。"
            exit 9
        fi
        ec2_action
    fi;;

    status)
        option_check ${ACTION}
        cat << EOF > ${TMP}
        ===================== ============
        NAME_TAG      STATUS
        ===================== ============
EOF
        if [[ -z ${MODE} ]] ; then
            if [[ 0 -lt $(echo ${HOST} | grep \, | wc -l) ]] ; then
                for H in $(echo ${HOST} | tr "," " ")
                do
                    HOST=${H}
                    ec2_status >> ${TMP}
                done
            else
                ec2_status >> ${TMP}
            fi
        else
            ec2_list | while read LINE
            do
                HOST=${LINE}
                ec2_status >> ${TMP}
            done
        fi

        column -t ${TMP}
        rm ${TMP};;

    list)
        cat << EOF > ${TMP}
        =====================
        NAME_TAG
        =====================
EOF
        ec2_list >> ${TMP}
        column -t ${TMP}
        rm ${TMP}

esac

福島 和弥 (記事一覧)

2019/10 入社

AWS CLIが好きです。