AWS CLI One-Liners for EC2 and S3 I Use Weekly

The console is fine for exploring; the CLI is faster once you know what you're looking for.

Instances missing a required tag

aws ec2 describe-instances \
  --query "Reservations[].Instances[?!not_null(Tags[?Key=='Owner'].Value)]" \
  --output table

Stopped instances still costing money (attached EBS)

aws ec2 describe-instances \
  --filters "Name=instance-state-name,Values=stopped" \
  --query "Reservations[].Instances[].[InstanceId,LaunchTime]" \
  --output table

Unattached EBS volumes

aws ec2 describe-volumes \
  --filters Name=status,Values=available \
  --query "Volumes[].[VolumeId,Size,CreateTime]" \
  --output table

S3 buckets with no lifecycle policy

for b in $(aws s3api list-buckets --query "Buckets[].Name" --output text); do
  aws s3api get-bucket-lifecycle-configuration --bucket "$b" >/dev/null 2>&1 \
    || echo "$b"
done

Total size of a bucket without listing every object

aws cloudwatch get-metric-statistics \
  --namespace AWS/S3 --metric-name BucketSizeBytes \
  --dimensions Name=BucketName,Value=my-bucket Name=StorageType,Value=StandardStorage \
  --start-time "$(date -u -d '-2 days' +%FT%TZ)" --end-time "$(date -u +%FT%TZ)" \
  --period 86400 --statistics Average

Snapshot an RDS instance right now

aws rds create-db-snapshot \
  --db-instance-identifier prod-db \
  --db-snapshot-identifier prod-db-manual-$(date +%Y%m%d%H%M)

The untagged-instance and unattached-volume queries alone catch most of the drift that shows up as a surprise on the monthly bill.