您可能會用到的AWS CLI Shell腳本。主要功能有根據名字/類別管理EC二、RDS資源,建立資源時自動添加標籤,建立EC2實例時可附加捲、定義用戶數據文件。可用-h或--help查看支持的命令和參數,GitHub源碼。git
支持的命令:
EC2github
Usage: ./ec2.sh [command] [args ...] Commands: create-image [instance_name] [image_name] [tags] Create an AMI from an EC2 instance delete-image [image_name] Delete image by name start-instance [instance_name] Start an EC2 instance start-instances [category_name] Start EC2 instances by category stop-instance [instance_name] Stop an EC2 instance stop-instances [category_name] Stop EC2 instances by category reboot-instance [instance_name] Reboot an EC2 instance reboot-instances [category_name] Reboot EC2 instances by category terminate-instance [instance_name] Terminate an EC2 instance terminate-instances [category_name] Terminate EC2 instances by category run-instance [instance_name] [image_name] [options] Launch an instance using an AMI Options: --device-snapshot-name One block device snapshot name --init-file an user data file --tags One or more tags create-snapshot [instance_name] [device] [snapshot_name] [tags] Creates a snapshot of the specified volume for an instance delete-snapshot [snapshot_name] Deletes the specified snapshot attach-volume [snapshot_name] [instance_name] [device] [tags] Create a volume from a snapshot, and then attach the volume to an instance associate-address [instance_name] [public_ip] Associates an Elastic IP address with an instance replace-route [route_table_name] [nat_instance_name] [cidr] Replaces an existing route within a route table in a VPC
RDS數據庫
Usage: ./rds.sh [delete|restore] [args ...] Commands: delete [db-instance-identifier] Delete a DB instance restore [db-instance-identifier] [vpc-security-group-ids] Create a new DB instance from a DB snapshot
Cloud Watchjson
Usage: ./cloudwatch.sh [cpu] [instance_name] [sns_topic_arn]
公用方法common.shapi
#!/bin/bash INSTANCE_ID_REGEX="i-\w{8,17}" IMAGE_ID_REGEX="ami-\w{8,17}" VOLUME_ID_REGEX="vol-\w{8,17}" SNAPSHOT_ID_REGEX="snap-\w{8,17}" ROUTETABLE_ID_REGEX="rtb-\w{8,17}" query_instance_id_by_name() { instance_id=$(aws ec2 describe-instances --filter Name=tag:Name,Values="$1" Name=instance-state-name,Values=pending,running,stopped \ --query 'Reservations[0].[Instances[0].InstanceId]' | grep -o -E "$INSTANCE_ID_REGEX") echo ${instance_id} } query_instance_ids_by_category() { instance_ids=$(aws ec2 describe-instances --filter Name=tag:Category,Values="$1" Name=instance-state-name,Values=pending,running,stopped \ --query 'Reservations[*].[Instances[*].InstanceId]' | grep -o -E "$INSTANCE_ID_REGEX") echo ${instance_ids} } wait_instance_ok() { instance_id=$(aws ec2 describe-instances --filter Name=tag:Name,Values="$1" Name=instance-state-name,Values=pending,running \ --query 'Reservations[0].[Instances[0].InstanceId]' | grep -o -E "$INSTANCE_ID_REGEX") check_instance_status ${instance_id} } check_instance_status() { while true do ok_count=$(aws ec2 describe-instance-status --instance-id $1 | grep -c ok) if [[ "$ok_count" -eq 2 ]]; then break else echo "Waiting ..." sleep 5 fi done } describe_running_instances() { instances=$(aws ec2 describe-instances --filter Name=instance-state-name,Values=running \ --query 'Reservations[*].Instances[*].{State:State.Name,Ip:PrivateIpAddress,InstanceId:InstanceId,Name:Tags[0].Value}') echo ${instances} } query_image_id_by_name() { image_id=$(aws ec2 describe-images --filter Name=name,Values="$1" --query Images[0].[ImageId] | grep -o -E "$IMAGE_ID_REGEX") echo ${image_id} } query_volume_id_by_name() { id=$(aws ec2 describe-volumes --filter Name=tag:Name,Values="$1" --query Volumes[0].[VolumeId] | grep -o -E "$VOLUME_ID_REGEX") echo ${id} } query_volume_ids_by_name() { id=$(aws ec2 describe-volumes --filter Name=tag:Name,Values="$1" --query Volumes[*].[VolumeId] | grep -o -E "$VOLUME_ID_REGEX") echo ${id} } query_volume_id_by_instance_id_and_device() { id=$(aws ec2 describe-volumes --filter Name=attachment.instance-id,Values="$1" Name=attachment.device,Values=$2 \ --query Volumes[0].[VolumeId] | grep -o -E "$VOLUME_ID_REGEX") echo ${id} } query_snapshot_id_by_name() { snapshot_id=$(aws ec2 describe-snapshots --filter Name=tag:Name,Values="$1" --query Snapshots[0].[SnapshotId] | grep -o -E "$SNAPSHOT_ID_REGEX") echo ${snapshot_id} } query_snapshot_ids_by_image_id() { snapshot_ids=$(aws ec2 describe-snapshots --query Snapshots[*].[SnapshotId][*] --filter Name=description,Values=*"$1"* | grep -o -E "$SNAPSHOT_ID_REGEX") echo ${snapshot_ids} } query_route_table_id_by_name() { id=$(aws ec2 describe-route-tables --filter Name=tag:Name,Values="$1" --query RouteTables[0].RouteTableId | grep -o -E "$ROUTETABLE_ID_REGEX") echo ${id} } query_elb_instance_ids() { ids=$(aws elb describe-load-balancers --load-balancer-name "$1" --query LoadBalancerDescriptions[0].[Instances[*].[InstanceId]] | grep -o -E "$INSTANCE_ID_REGEX") echo ${ids} } create_tags_with_name() { resource_id=$1 name=$2 tags=$3; if [[ -z ${resource_id} ]]; then return 1 fi if [[ ${tags} ]]; then echo "Add tags: ${tags}" fi aws ec2 create-tags --resources ${resource_id} --tags Key=Name,Value="${name}" ${tags} echo }
EC2腳本ec2.shbash
#!/bin/bash . $(dirname $0)/common.sh # 根據Instance Name建立image並添加標籤 create_image() { instance_name=$1 image_name=$2 tags=$3 echo "Create image for instance ${instance_name}" instance_id=$(query_instance_id_by_name "${instance_name}") image_id=$(aws ec2 create-image --instance-id "${instance_id}" --name "${image_name}" --description "${image_name}" --no-reboot --query ImageId) image_id=${image_id//\"/} echo "ImageId: $image_id" create_tags_with_name "${image_id}" "${image_name}" "${tags}" } # 刪除AMI delete_image() { image_name=$1 echo "Delete image ${image_name}" image_id=$(query_image_id_by_name "${image_name}") echo "Image id: ${image_id}" echo "Deregister image $image_id" aws ec2 deregister-image --image-id "${image_id}" snapshot_ids=$(query_snapshot_ids_by_image_id "${image_id}") for snapshot_id in ${snapshot_ids} do echo "Delete snapshot ${snapshot_id}" aws ec2 delete-snapshot --snapshot-id "${snapshot_id}" done echo } # 根據Name啓動EC2 Instance start_instance() { id=$(query_instance_id_by_name "$1") aws ec2 start-instances --instance-ids ${id} } # 根據類別啓動EC2 Instance start_instances() { ids=$(query_instance_ids_by_category "$1") aws ec2 start-instances --instance-ids ${ids} } # 根據Name中止EC2 Instance stop_instance() { id=$(query_instance_id_by_name "$1") aws ec2 stop-instances --instance-ids ${id} } # 根據類別中止EC2 Instance stop_instances() { ids=$(query_instance_ids_by_category "$1") aws ec2 stop-instances --instance-ids ${ids} } # 根據Name重啓EC2 Instance reboot_instance() { id=$(query_instance_id_by_name "$1") aws ec2 reboot-instances --instance-ids ${id} } # 根據類別重啓EC2 Instance reboot_instances() { ids=$(query_instance_ids_by_category "$1") aws ec2 reboot-instances --instance-ids ${ids} } # 根據Name終止EC2 Instance terminate_instance() { id=$(query_instance_id_by_name "$1") echo "terminate instance, instance name: $1 instance id: ${id}" aws ec2 modify-instance-attribute --instance-id "${id}" --no-disable-api-termination aws ec2 terminate-instances --instance-ids ${id} echo } # 根據類別終止EC2 Instance terminate_instances() { ids=$(query_instance_ids_by_category "$1") echo "terminate instances, category: $1 instance-ids: ${ids}" for id in ${ids} do aws ec2 modify-instance-attribute --instance-id "${id}" --no-disable-api-termination done aws ec2 terminate-instances --instance-ids ${ids} echo } # 從Image建立EC2 Instance,EC2配置從JSON文件讀取,能夠附加一個Volume,能夠使用用戶數據文件,能夠添加標籤 run_instance() { instance_name=$1 image_name=$2 device_snapshot_name=$3 init_file=$4 tags=$5 block_device_mappings=" " if [[ "${device_snapshot_name}" ]]; then snapshot_id=$(query_snapshot_id_by_name "${device_snapshot_name}") if [[ "${snapshot_id}" ]]; then block_device_mappings="--block-device-mappings DeviceName=/dev/sdf,Ebs={SnapshotId=${snapshot_id},DeleteOnTermination=true,VolumeType=gp2}" else echo "Please provide a valid volume snapshot name" exit 1 fi fi image_id=$(query_image_id_by_name "${image_name}") echo "Create EC2 instance ${instance_name} from image ${image_name}(${image_id})" if [[ "$init_file" ]]; then instance_id=$(aws ec2 run-instances --image-id "${image_id}" ${block_device_mappings} --cli-input-json file://json/"${instance_name}".json \ --user-data file://"${init_file}" --query 'Instances[0].[InstanceId]' | grep -o -E "${INSTANCE_ID_REGEX}") else instance_id=$(aws ec2 run-instances --image-id "${image_id}" ${block_device_mappings} --cli-input-json file://json/"${instance_name}".json \ --query 'Instances[0].[InstanceId]' | grep -o -E "${INSTANCE_ID_REGEX}") fi create_tags_with_name "${instance_id}" "${instance_name}" "${tags}" } # 爲EC2 Instance的指定卷建立快照並刪除之前同名快照 create_snapshot() { instance_name=$1 device=$2 snapshot_name=$3 tags=$4 instance_id=$(query_instance_id_by_name "${instance_name}") delete_snapshot "${snapshot_name}" volume_id=$(query_volume_id_by_instance_id_and_device ${instance_id} ${device}) if [[ "${volume_id}" ]]; then echo "create snapshot for volume: ${device} of instance ${instance_name}" snapshot_id=$(aws ec2 create-snapshot --volume-id ${volume_id} | grep -o -E "${SNAPSHOT_ID_REGEX}") create_tags_with_name "${snapshot_id}" "${snapshot_name}" "${tags}" fi } # 根據名稱刪除快照 delete_snapshot() { snapshot_id=$(query_snapshot_id_by_name "$1") if [[ "${snapshot_id}" ]]; then echo "delete snapshot: $1" aws ec2 delete-snapshot --snapshot-id ${snapshot_id} fi } # 從快照建立卷並刪除舊的重名卷,而後將卷鏈接到Instance的指定device attach_volume() { snapshot_name=$1 instance_name=$2 device=$3 tags=$4 availability_zone="cn-north-1a" volume_name="$1-1a" snapshot_id=$(query_snapshot_id_by_name ${snapshot_name}) instance_id=$(query_instance_id_by_name ${instance_name}) if [[ -z "${snapshot_id}" ]]; then echo "Please provide valid snapshot name" exit 1 fi if [[ -z "${instance_id}" ]]; then echo "Please provide valid instance name" exit 1 fi old_volume_ids=$(query_volume_ids_by_name "${volume_name}") for id in ${old_volume_ids} do echo "delete old volume: $id" aws ec2 delete-volume --volume-id ${id} done echo "create volume ${volume_name} from snapshot ${snapshot_name}(${snapshot_id})" volume_id=$(aws ec2 create-volume --snapshot-id ${snapshot_id} --availability-zone ${availability_zone} --volume-type gp2 --query 'VolumeId' \ | grep -o -E "${VOLUME_ID_REGEX}") count=0 while [[ "${count}" -le 0 ]] do echo "Creating volume ${volume_name} ..." count=$(aws ec2 describe-volumes --volume-ids ${volume_id} --query Volumes[0].State | grep -c available) sleep 3 done echo "attach volume: ${volume_name} to instance ${instance_name}" aws ec2 attach-volume --volume-id ${volume_id} --instance-id ${instance_id} --device ${device} create_tags_with_name "${volume_id}" "${volume_name}" "${tags}" } # 關聯彈性IP到Instance associate_address() { instance_id=$(query_instance_id_by_name "$1") aws ec2 associate-address --instance-id ${instance_id} --public-ip $2 } # 更新NAT Instance路由 replace_route() { echo "update route table: $1" route_table_id=$(query_route_table_id_by_name "$1") nat_instance_id=$(query_instance_id_by_name "$2") cidr=$3 aws ec2 replace-route --route-table-id ${route_table_id} --destination-cidr-block ${cidr} --instance-id ${nat_instance_id} } echo_usage() { echo "Usage: $0 [command] [args ...]" echo "Commands:" echo " create-image [instance_name] [image_name] [tags] Create an AMI from an EC2 instance" echo " delete-image [image_name] Delete image by name" echo " start-instance [instance_name] Start an EC2 instance" echo " start-instances [category_name] Start EC2 instances by category" echo " stop-instance [instance_name] Stop an EC2 instance" echo " stop-instances [category_name] Stop EC2 instances by category" echo " reboot-instance [instance_name] Reboot an EC2 instance" echo " reboot-instances [category_name] Reboot EC2 instances by category" echo " terminate-instance [instance_name] Terminate an EC2 instance" echo " terminate-instances [category_name] Terminate EC2 instances by category" echo " run-instance [instance_name] [image_name] [options] Launch an instance using an AMI" echo " Options:" echo " --device-snapshot-name One block device snapshot name" echo " --init-file an user data file" echo " --tags One or more tags" echo " create-snapshot [instance_name] [device] [snapshot_name] [tags] Creates a snapshot of the specified volume for an instance" echo " delete-snapshot [snapshot_name] Deletes the specified snapshot" echo " attach-volume [snapshot_name] [instance_name] [device] [tags] Create a volume from a snapshot, and then attach the volume to an instance" echo " associate-address [instance_name] [public_ip] Associates an Elastic IP address with an instance" echo " replace-route [route_table_name] [nat_instance_name] [cidr] Replaces an existing route within a route table in a VPC" } if test @$1 = @--help -o @$1 = @-h; then echo_usage exit 0 fi if [[ $# -lt 2 ]]; then echo_usage exit 1 fi case "$1" in create-image) create_image "$2" "$3" "$4" ;; delete-image) delete_image "$2" ;; start-instance) start_instance "$2" ;; start-instances) start_instances "$2" ;; stop-instance) stop_instance "$2" ;; stop-instances) stop_instances "$2" ;; reboot-instance) reboot_instance "$2" ;; reboot-instances) reboot_instances "$2" ;; terminate-instance) terminate_instance "$2" ;; terminate-instances) terminate_instances "$2" ;; run-instance) args=`getopt -l init-file:,device-snapshot-name:,tags: -- "$@"` if [[ $? != 0 ]] ; then exit 1 fi instance_name=$2 image_name=$3 device_snapshot_name="" init_file="" tags="" eval set -- "${args}" while true do case "$1" in --device-snapshot-name) device_snapshot_name="$2" shift 2 ;; --init-file) init_file="$2" shift 2 ;; --tags) tags="$2" shift 2 ;; --) shift break ;; esac done run_instance "${instance_name}" "${image_name}" "${device_snapshot_name}" "${init_file}" "${tags}" ;; create-snapshot) create_snapshot "$2" "$3" "$4" "$5" ;; delete-snapshot) delete_snapshot "$2" ;; attach-volume) attach_volume "$2" "$3" "$4" "$5" ;; associate-address) associate_address "$2" "$3" ;; replace-route) replace_route "$2" "$3" "$4" ;; *) exit 1 ;; esac
從image運行instance時須要使用json配置文件,位置在json目錄下,名稱要與instance name相同,內容以下;
示例ec2.jsonoracle
{ "DryRun": false, "KeyName": "AWS Prod Key Pair", "SecurityGroupIds": [ "sg-1361c577" ], "InstanceType": "m4.large", "Placement": { "AvailabilityZone": "cn-north-1a", "Tenancy": "default" }, "Monitoring": { "Enabled": false }, "DisableApiTermination": true, "InstanceInitiatedShutdownBehavior": "stop", "NetworkInterfaces": [ { "DeviceIndex": 0, "SubnetId": "subnet-d45208b1", "PrivateIpAddress": "10.184.12.246", "DeleteOnTermination": true, "AssociatePublicIpAddress": false } ], "EbsOptimized": false }
示例app
$ ./ec2.sh run-instance test-app1 test-app1 --tags "Key=CCX,Value=DSC003 Key=Project,Value=Test"
rds.shide
#!/bin/bash # 根據db-instance-identifier刪除數據庫,刪除前先建立快照,並將db-snapshot-identifier保存在文件中 delete() { echo "deleting database $1 ..." snapshot_id="$1-$(date +%Y%m%d)" aws rds delete-db-instance --db-instance-identifier "$1" --no-skip-final-snapshot --final-db-snapshot-identifier "${snapshot_id}" echo "${snapshot_id}" > "$(dirname $0)/$1.snapshot.id" } # 從最近的快照恢復數據庫,數據庫配置從json文件讀取,恢復成功後指定security group,並輸出恢復日誌到文件中 restore() { log_file="$(dirname $0)/restore.log" id_file="$(dirname $0)/$1.snapshot.id" snapshot_id=$(cat ${id_file}) echo "Restore database $1 from snapshot ${snapshot_id}" | tee ${log_file} aws rds restore-db-instance-from-db-snapshot --db-snapshot-identifier "${snapshot_id}" --cli-input-json file://json/"$1".json | tee ${log_file} count=0 while [[ "${count}" -le 0 ]] do echo "Creating database $1 ..." count=$(aws rds describe-db-instances --db-instance-identifier "$1" --query 'DBInstances[0].[DBInstanceStatus]' | grep -c available) sleep 5 done echo "Modify database $1" | tee ${log_file} aws rds modify-db-instance --db-instance-identifier "$1" --vpc-security-group-ids $2 | tee ${log_file} } echo_usage() { echo "Usage: $0 [delete|restore] [args ...]" echo "Commands:" echo " delete [db-instance-identifier] Delete a DB instance" echo " restore [db-instance-identifier] [vpc-security-group-ids] Create a new DB instance from a DB snapshot" } if test @$1 = @--help -o @$1 = @-h; then echo_usage exit 0 fi if [[ $# -lt 2 ]]; then echo_usage exit 1 fi case "$1" in delete) delete "$2" ;; restore) restore "$2" "$3" ;; *) exit 1 ;; esac
示例dn.jsonlua
{ "DBInstanceIdentifier": "test", "DBInstanceClass": "db.r3.large", "Port": 1521, "AvailabilityZone": "cn-north-1a", "DBSubnetGroupName": "test-db", "MultiAZ": false, "PubliclyAccessible": false, "AutoMinorVersionUpgrade": true, "LicenseModel": "license-included", "DBName": "test", "Engine": "oracle-se1", "OptionGroupName": "default:oracle-se1-11-2", "StorageType": "standard", "CopyTagsToSnapshot": true }
cloudwatch.sh
#!/bin/bash . $(dirname $0)/common.sh # 當EC2 Instance CPU利用率超過90%時發送郵件告警 cpu() { instance_name=$1 sns_topic_arn=$2 instance_id=$(query_instance_id_by_name "${instance_name}") aws cloudwatch put-metric-alarm --alarm-name "cpu-${instance_name}" --alarm-description "Alarm when CPU exceeds 90 percent" --metric-name CPUUtilization \ --namespace AWS/EC2 --statistic Average --period 300 --threshold 90 --comparison-operator GreaterThanThreshold \ --dimensions "Name=InstanceId,Value=${instance_id}" --evaluation-periods 2 --unit Percent --alarm-actions $2 } echo_usage() { echo "Usage: $0 [cpu] [instance_name] [sns_topic_arn]" } if test @$1 = @--help -o @$1 = @-h; then echo_usage exit 0 fi if [[ $# -lt 2 ]]; then echo_usage exit 1 fi case "$1" in "cpu") cpu "$2" "$3" ;; *) exit 1 ;; esac