Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
- function msg() {
- printf "$*" >&2
- }
- # ヘルプメッセージ
- function usage() {
- printf "usage: %s <EC2 Instance ID> [<AMI ID>]\n\n" ${0##*/} >&2
- exit
- }
- # 英小文字 -> 英大文字
- function toupper() {
- echo $1 | tr 'a-z' 'A-Z'
- }
- #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
- EC2_INSTANCE_ID=$1
- AMI_ID=$2
- # 必要なコマンドがインストールされているか確認
- cmd_list='
- aws
- jq
- '
- cmd_miss=0
- for cmd in $(echo $cmd_list | xargs); do
- if [ "$(which $cmd 2>&1)" = "" ]; then
- echo "ERROR: コマンドが見つかりません: $cmd"
- cmd_miss=1
- fi
- done
- if [ $cmd_miss != 0 ]; then exit; fi
- # 引数の確認
- if [ "$EC2_INSTANCE_ID" = "" ]; then
- # EC2_INSTANCE_ID の指定がなかったら終了
- usage
- fi
- # クレデンシャルの確認(クレデンシャルが設定されていなかったら終了)
- msg "checking identity...\r"
- aws sts get-caller-identity >/dev/null || exit
- msg " \r"
- # 必要な情報の収集
- ## EC2インスタンスからデバイス名とボリュームIDのリスト取得
- ## ex) [{"DeviceName":"/dev/sda1","VolumeId":"vol-1234abcd"}, {...}]
- msg "collecting volume devices...\r" >&2
- EC2_DESCRIBE_JSON=$(aws ec2 describe-instances --instance-ids ${EC2_INSTANCE_ID})
- if [ "$?" != "0" ]; then
- # EC2インスタンスの情報収集で失敗したら終了
- usage
- fi
- dev_vol_json=$(echo $EC2_DESCRIBE_JSON | jq -c '.[][]|.Instances[].BlockDeviceMappings[]|{"DeviceName":.DeviceName,"VolumeId":.Ebs.VolumeId}')
- DEVICES=$(echo ${dev_vol_json} | jq -r '.DeviceName' | sort)
- DEVICES_UPCASE=$(echo $DEVICES | sed -Ee 's|/[^ ]*/||'g | tr 'a-z' 'A-Z')
- msg " \r"
- if [ "$AMI_ID" != "" ]; then
- # AMIから取得したデバイスリストと比較して確認
- msg "checking ami...\r"
- AMI_DESCRIBE_JSON=$(aws ec2 describe-images --image-ids ${AMI_ID})
- AMI_DEVICES=$(echo $AMI_DESCRIBE_JSON | jq -r '.[][].BlockDeviceMappings[].DeviceName' | sort)
- if [ "$DEVICES" != "$AMI_DEVICES" ]; then
- echo "ERROR: 指定されたEC2インスタンスとAMIのデバイスが合っていません"
- usage
- fi
- msg " \r"
- # AMIからスナップショットIDを取得
- msg "collecting snapshot ids from ami...\r"
- dev_snap_json=$(echo $AMI_DESCRIBE_JSON | jq -c '.[][].BlockDeviceMappings[]|{"DeviceName":.DeviceName,"SnapshotId":.Ebs.SnapshotId}')
- msg " \r"
- mode=0
- note=''
- else
- # AMI ID の指定がなかったらテンプレートモード
- # テンプレートモード
- AMI_ID="***"
- mode=1
- note='
- # 実行時に、下記環境変数に手動でパラメータを補って下さい(***の部分)
- # AMI_ID
- # SNAP_ID_(デバイス名)
- '
- fi
- # 各ボリュームのタグ・AZ・タイプ情報を取得
- msg "collecting volume infos...\r"
- vol_info_json=$(
- for vol_id in $(echo ${dev_vol_json} | jq -r '.VolumeId'); do
- aws ec2 describe-volumes --volume-id ${vol_id} \
- | jq -c '.[][]|{"VolumeId":.VolumeId,"Tags":.Tags,"AvailabilityZone":.AvailabilityZone,"VolumeType":.VolumeType}'
- done
- )
- msg " \r\n"
- #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
- ### 結果をもとに環境変数に登録
- show_SNAP_ID() {
- for dev in $DEVICES; do
- case $mode in
- 0)
- snap_id=$(echo ${dev_snap_json} | jq -r '.|select(.DeviceName=="'${dev}'").SnapshotId')
- ;;
- *)
- snap_id="***"
- ;;
- esac
- printf "SNAP_ID_%s=%s\n" $(toupper ${dev##*/}) $snap_id
- done
- for DEV in $DEVICES_UPCASE; do
- printf "echo SNAP_ID_%s = \${SNAP_ID_%s}\n" $DEV $DEV
- done
- }
- ### スナップショットからEBSボリューム作成
- show_cmd_create_volume_new() {
- for dev in $DEVICES; do
- vol_id=$(echo ${dev_vol_json} | jq -r '.|select(.DeviceName=="'${dev}'").VolumeId')
- AZ=$(echo ${vol_info_json} | jq -r '.|select(.VolumeId=="'${vol_id}'").AvailabilityZone')
- TYPE=$(echo ${vol_info_json} | jq -r '.|select(.VolumeId=="'${vol_id}'").VolumeType')
- # /dev/sda1 -> SDA1
- DEV=$(toupper ${dev##*/})
- printf "NEW_VOLUME_%s=\$(aws ec2 create-volume --availability-zone %s --volume-type %s --snapshot-id \${SNAP_ID_%s} | jq -r '.VolumeId')\n" $DEV $AZ $TYPE $DEV
- done
- for DEV in $DEVICES_UPCASE; do
- printf "echo NEW_VOLUME_%s = \${NEW_VOLUME_%s}\n" $DEV $DEV
- done
- }
- ### 結果をもとに環境変数に登録
- show_CUR_VOLUME() {
- for dev in $DEVICES; do
- DEV=$(toupper ${dev##*/})
- vol_id=$(echo ${dev_vol_json} | jq -r '.|select(.DeviceName=="'${dev}'").VolumeId')
- printf "CUR_VOLUME_%s=%s\n" $DEV $vol_id
- done
- for DEV in $DEVICES_UPCASE; do
- printf "echo CUR_VOLUME_%s = \${CUR_VOLUME_%s}\n" $DEV $DEV
- done
- }
- ### 現在のEBSボリュームのタグ情報を確認 -- CUR
- ### 新しいEBSボリュームのタグ情報を確認 -- NEW
- show_cmd_describe_volumes_tags() {
- for DEV in $DEVICES_UPCASE; do
- printf "aws ec2 describe-volumes --volume-ids \${%s_VOLUME_%s} | jq -rc '.Volumes[]|.Attachments[].Device,.Tags' | xargs -n2\n" $1 $DEV
- done
- }
- ### 新規EBSボリュームにタグを付与
- show_cmd_create_tags() {
- for dev in $DEVICES; do
- DEV=$(toupper ${dev##*/})
- vol_id=$(echo ${dev_vol_json} | jq -r '.|select(.DeviceName=="'${dev}'").VolumeId')
- vol_tags=$(echo ${vol_info_json} | jq -c '.|select(.VolumeId=="'${vol_id}'")|.Tags')
- if [ "$vol_tags" = "null" ]; then
- echo "# Tagなし : $vol_id - NEW_VOLUME_$DEV"
- else
- tag_name=''
- tag_other=''
- for tagpair in $(echo "$vol_tags" | jq -c '.[]'); do
- key=$(echo $tagpair | jq -r .Key)
- value=$(echo $tagpair | jq -r .Value)
- # Name -> それ以外の順で表示
- case "$key" in
- Name | name)
- tag_name="$tag_name $(printf 'Key=%s,Value=%s' $key $value)"
- ;;
- *)
- tag_other="$tag_other $(printf 'Key=%s,Value=%s' $key $value)"
- ;;
- esac
- done
- printf 'aws ec2 create-tags --resources ${NEW_VOLUME_%s} --tags%s%s\n' $DEV "$tag_name" "$tag_other"
- fi
- done
- }
- ### 差分確認(日付やAttachments以外の差分を確認する)
- show_cmd_diff() {
- for DEV in $DEVICES_UPCASE; do
- printf 'diff -ub <(aws ec2 describe-volumes --volume-ids ${CUR_VOLUME_%s}) <(aws ec2 describe-volumes --volume-ids ${NEW_VOLUME_%s})\n' $DEV $DEV
- done
- }
- ### ボリュームのデタッチ
- show_cmd_detach_volume() {
- for DEV in $DEVICES_UPCASE; do
- printf "aws ec2 detach-volume --volume-id \${CUR_VOLUME_%s}\n" $DEV
- done
- }
- ### デタッチされたことの確認(availableになっていること) -- CUR
- ### アタッチされたことの確認(in-useになっていること) -- NEW
- show_cmd_describe_volumes_status() {
- printf 'aws ec2 describe-volumes --volume-ids'
- for DEV in $DEVICES_UPCASE; do
- printf " \${%s_VOLUME_%s}" $1 $DEV
- done
- printf " | jq -r '.Volumes[]|.VolumeId,.State' | xargs -n2\n"
- }
- ### ボリュームのアタッチ
- show_cmd_attach_volume() {
- for dev in $DEVICES; do
- DEV=$(toupper ${dev##*/})
- printf "aws ec2 attach-volume --volume-id \${NEW_VOLUME_%s} --instance-id \${EC2_INSTANCE_ID} --device %s\n" $DEV $dev
- done
- }
- ### 標準出力が端末のときは色を付ける
- cmd_colorize() {
- if [ -t 1 ]; then
- ruby -pe '$_.gsub!(/\A([^#*]+)?(***)?(#.*)?(\s*)?\Z/, "\e[97m\\1\e[93;1;4m\\2\e[m\e[32m\\3\e[m\\4")'
- else
- cat
- fi
- }
- #----#----#----#----#----#----#----#----#----#----#----#----#----#----#----#
- # コメント行を緑色にしつつ出力
- cat <<EOF | cmd_colorize
- # --------------------------------------------------------------------------------
- # ${0##*/} $*
- # --------------------------------------------------------------------------------
- $note
- EC2_INSTANCE_ID=${EC2_INSTANCE_ID}
- AMI_ID=${AMI_ID}
- echo EC2_INSTANCE_ID = \${EC2_INSTANCE_ID}
- echo AMI_ID = \${AMI_ID}
- ### AMIからスナップショットIDを確認
- aws ec2 describe-images --image-ids \${AMI_ID} | jq -r '.Images[].BlockDeviceMappings[]|.DeviceName,.Ebs.SnapshotId' | xargs -n2
- ### 結果をもとに環境変数に登録
- $( show_SNAP_ID )
- ### スナップショットからEBSボリューム作成
- $( show_cmd_create_volume_new )
- ### EC2インスタンスに接続されているEBSボリュームのIDを確認
- aws ec2 describe-instances --instance-ids \${EC2_INSTANCE_ID} | jq -r '.[][].Instances[].BlockDeviceMappings[]|.DeviceName,.Ebs.VolumeId' | xargs -n2
- ### 結果をもとに環境変数に登録
- $( show_CUR_VOLUME )
- ### 現在のEBSボリュームのタグ情報を確認
- $( show_cmd_describe_volumes_tags CUR )
- ### 新規EBSボリュームにタグを付与
- $( show_cmd_create_tags )
- ### 新しいEBSボリュームのタグ情報を確認
- $( show_cmd_describe_volumes_tags NEW )
- ### 差分確認(日付やAttachments以外の差分を確認する)
- $( show_cmd_diff )
- ### インスタンス停止
- echo \${EC2_INSTANCE_ID} # ${EC2_INSTANCE_ID}
- aws ec2 stop-instances --instance-ids \${EC2_INSTANCE_ID}
- aws ec2 wait instance-stopped --instance-ids \${EC2_INSTANCE_ID} && echo 'stopped.'
- ### ボリュームのデタッチ
- $( show_cmd_detach_volume )
- ### デタッチされたことの確認(availableになっていること)
- $( show_cmd_describe_volumes_status CUR )
- ### ボリュームのアタッチ
- $( show_cmd_attach_volume )
- ### アタッチされたことの確認(in-useになっていること)
- $( show_cmd_describe_volumes_status NEW )
- ### インスタンス起動
- aws ec2 start-instances --instance-ids \${EC2_INSTANCE_ID}
- aws ec2 wait instance-running --instance-ids \${EC2_INSTANCE_ID} && echo 'running.'
- aws ec2 wait instance-status-ok --instance-ids \${EC2_INSTANCE_ID} && echo 'status ok.'
- EOF
Add Comment
Please, Sign In to add comment