AB
Dive deeper into AWS CLI with advanced commands, scripting techniques, automation strategies, and essential best practices
Building on the intermediate commands covered in Part 1, let’s explore more advanced AWS CLI capabilities that can significantly enhance your cloud infrastructure management.
AWS CLI supports JMESPath, a query language for JSON that allows you to extract specific data from command output:
aws ec2 describe-instances --query "Reservations[*].Instances[*].[InstanceId,State.Name]" --output table
-------------------------
| DescribeInstances |
+-------------+---------+
| i-1234abcd | running|
| i-5678efgh | stopped|
+-------------+---------+
aws ec2 describe-instances --filters "Name=instance-type,Values=t2.micro" --query "Reservations[*].Instances[*].InstanceId" --output text
i-1234abcd i-5678efgh
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--parameters commands="yum update -y" \
--targets "Key=tag:Environment,Values=Production" \
--comment "Patching production servers"
yum update -y
command on all EC2 instances tagged with “Environment=Production”.aws ssm get-parameter --name "/application/database/password" --with-decryption
{
"Parameter": {
"Name": "/application/database/password",
"Type": "SecureString",
"Value": "MySecurePassword123!",
"Version": 1,
"LastModifiedDate": "2023-09-01T12:00:00.000Z",
"ARN": "arn:aws:ssm:us-east-1:123456789012:parameter/application/database/password"
}
}
aws cloudwatch put-dashboard --dashboard-name "MyAppMonitoring" --dashboard-body file://dashboard.json
dashboard.json
.aws cloudwatch put-composite-alarm \
--alarm-name "HighCPUAndMemoryAlarm" \
--alarm-rule "(ALARM(HighCPUAlarm) AND ALARM(HighMemoryAlarm))"
aws rds create-db-snapshot \
--db-instance-identifier my-database \
--db-snapshot-identifier my-database-snapshot-$(date +%Y-%m-%d)
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier my-restored-db \
--db-snapshot-identifier my-database-snapshot-2023-09-15
aws ecs update-service \
--cluster my-cluster \
--service my-service \
--desired-count 5 \
--force-new-deployment
aws ecs run-task \
--cluster my-cluster \
--task-definition my-task:3 \
--count 1 \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[subnet-12345678],securityGroups=[sg-12345678]}"
aws route53 change-resource-record-sets \
--hosted-zone-id Z1D633PJN98FT9 \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "www.example.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{ "Value": "192.0.2.1" }]
}
}]
}'
www.example.com
to the IP address 192.0.2.1.aws route53 get-health-check-status --health-check-id 1234abcd-56ef-78gh-90ij-1234klmnopqr
One of the most powerful aspects of AWS CLI is the ability to automate repetitive tasks. This section explores how to build scripts and automate common workflows.
Here’s a basic script to back up the content of an S3 bucket to another bucket:
#!/bin/bash
# Backup script for S3 bucket
SOURCE_BUCKET="source-bucket"
BACKUP_BUCKET="backup-bucket"
TIMESTAMP=$(date +%Y-%m-%d-%H-%M)
# Create a backup with timestamp
aws s3 sync s3://$SOURCE_BUCKET/ s3://$BACKUP_BUCKET/$TIMESTAMP/ \
--exclude "temporary/*"
# Output results
echo "Backup of $SOURCE_BUCKET completed to $BACKUP_BUCKET/$TIMESTAMP/"
This script finds and terminates EC2 instances that have been stopped for more than 30 days:
#!/bin/bash
# Find and terminate old stopped instances
# Get a list of stopped instances
STOPPED_INSTANCES=$(aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=stopped" \
--query "Reservations[*].Instances[*].[InstanceId,LaunchTime]" \
--output text)
# Calculate cutoff date (30 days ago)
CUTOFF_DATE=$(date -d "30 days ago" +%s)
# Process each instance
echo "$STOPPED_INSTANCES" | while read INSTANCE_ID LAUNCH_TIME; do
# Convert launch time to seconds since epoch
STOP_TIME=$(date -d "$LAUNCH_TIME" +%s)
# Check if older than cutoff
if [ $STOP_TIME -lt $CUTOFF_DATE ]; then
echo "Terminating old instance: $INSTANCE_ID (stopped since $(date -d @$STOP_TIME))"
aws ec2 terminate-instances --instance-ids $INSTANCE_ID
fi
done
Some AWS CLI commands require complex JSON input. Here’s how to handle this:
For a CloudFormation stack with complex parameters:
# File: stack-params.json
{
"StackName": "MyApplicationStack",
"Parameters": [
{
"ParameterKey": "EnvironmentType",
"ParameterValue": "Production"
},
{
"ParameterKey": "InstanceType",
"ParameterValue": "t3.large"
}
],
"Tags": [
{
"Key": "Department",
"Value": "Engineering"
}
]
}
aws cloudformation create-stack --cli-input-json file://stack-params.json
For simpler cases, you can use inline JSON:
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t2.micro \
--tag-specifications '[
{
"ResourceType": "instance",
"Tags": [
{
"Key": "Environment",
"Value": "Development"
},
{
"Key": "Project",
"Value": "TestProject"
}
]
}
]'
To run an S3 cleanup job every day at 2 AM:
# Add to crontab with: crontab -e
0 2 * * * /path/to/aws-s3-cleanup.sh >> /var/log/aws-cleanup.log 2>&1
On Windows, you can use Task Scheduler to run AWS CLI commands:
aws-backup.bat
):@echo off
aws s3 sync C:\Important-Files s3://my-backup-bucket/
Make your scripts more flexible by accepting parameters:
#!/bin/bash
# Dynamic EC2 instance creator
# Process command line arguments
INSTANCE_TYPE=${1:-t2.micro} # Default to t2.micro if not provided
AMI_ID=${2:-ami-0abcdef1234567890} # Default AMI if not provided
KEY_NAME=${3:-my-key} # Default key if not provided
# Launch instance
aws ec2 run-instances \
--image-id $AMI_ID \
--instance-type $INSTANCE_TYPE \
--key-name $KEY_NAME \
--tag-specifications "ResourceType=instance,Tags=[{Key=CreatedBy,Value=CLI-Script}]"
echo "Instance launched with type $INSTANCE_TYPE using AMI $AMI_ID"
./create-instance.sh t3.large ami-1234567890abcdef my-production-key
To maximize the effectiveness and security of your AWS CLI usage, follow these best practices:
Instead of storing credentials on EC2 instances:
aws ec2 associate-iam-instance-profile \
--instance-id i-1234567890abcdef \
--iam-instance-profile Name=EC2-S3-Access-Role
Commands:
# Create new access key
aws iam create-access-key --user-name MyUser
# After updating credentials file, remove old key
aws iam delete-access-key --user-name MyUser --access-key-id AKIAIOSFODNN7EXAMPLE
Security Benefit: Reduces the impact of leaked credentials.
aws iam put-user-policy \
--user-name DevUser \
--policy-name DevS3ReadOnly \
--policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "arn:aws:s3:::development-bucket/*"
}]
}'
--no-paginate
Option for Speedaws s3api list-objects --bucket my-large-bucket --no-paginate
--dry-run
for Testingaws ec2 start-instances --instance-ids i-1234567890abcdef --dry-run
--dry-run
where available.aws configure --profile production
aws configure --profile development
aws s3 ls --profile production
Robust error handling in Bash:
#!/bin/bash
# Script with error handling
# Set error flag to exit on any command failure
set -e
# Run AWS CLI command and capture the exit code
aws s3 mb s3://my-new-bucket
if [ $? -ne 0 ]; then
echo "Failed to create bucket. Exiting."
exit 1
fi
# Continue with successful execution
echo "Bucket created successfully!"
# Only run the second command if the first succeeds
aws ec2 stop-instances --instance-ids i-1234567890abcdef && \
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef --instance-type "{\"Value\":\"t3.large\"}"
Well-documented script example:
#!/bin/bash
# Purpose: Daily backup of critical databases
# Author: AWS Administrator
# Last Updated: 2023-09-15
#
# This script creates RDS snapshots and copies them to another region
# for disaster recovery purposes.
# Configuration variables
SOURCE_REGION="us-east-1"
BACKUP_REGION="us-west-2"
DB_INSTANCES=("prod-db-1" "prod-db-2")
RETENTION_DAYS=7
# Function to create a snapshot
create_snapshot() {
local db_instance=$1
local timestamp=$(date +%Y-%m-%d-%H-%M)
echo "Creating snapshot of $db_instance..."
aws rds create-db-snapshot \
--db-instance-identifier $db_instance \
--db-snapshot-identifier "${db_instance}-${timestamp}" \
--region $SOURCE_REGION
}
# Main execution
for db in "${DB_INSTANCES[@]}"; do
create_snapshot $db
done
# Delete old snapshots
# ...rest of script...
aws ec2 describe-instances help
Even experienced users encounter issues with AWS CLI. Here are common problems and their solutions:
aws configure
to set up your credentials.~/.aws/credentials
file exists and has correct entries.AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
if you use them.--debug
Flagaws s3 ls --debug
~/.aws/config
:[profile myprofile]
region = us-east-1
output = json
cli_history = enabled
#!/bin/bash
# Loop through multiple S3 buckets with a delay
for bucket in $(aws s3 ls | awk '{print $3}'); do
echo "Processing $bucket"
aws s3 ls s3://$bucket
# Sleep for 1 second between calls
sleep 1
done
~/.aws/config
:[default]
region = us-east-1
max_attempts = 5
retry_mode = adaptive
AWS CLI is a powerful tool that can significantly enhance your AWS management capabilities. From basic operations to complex automation, it offers flexibility and efficiency that the Management Console simply cannot match.
By mastering AWS CLI, you’ve gained a valuable skill that not only makes your daily AWS tasks more efficient but also opens up new possibilities for infrastructure automation and management.