CLI Practice Lab
Launch CloudShell, verify your identity and region, practise variables and queries, create a small S3 resource, diagnose common failures, and clean up.
Prerequisites
Use a training account
Do not run this lab in a production account. You will create one private S3 bucket, upload a tiny text file, and delete both before finishing.
Open CloudShell and Verify Context
Goal
Open a Bash shell that works the same way on Windows, macOS, and Linux. Confirm the AWS identity and region before making changes.
Estimated time: 10 minutes
- 1Sign in to the AWS Management Console
- 2Select
ap-south-1from the region selector - 3Choose the CloudShell terminal icon in the console header
- 4Wait until the prompt appears
aws --version
bash --version | head -n 1
jq --version
python3 --versionAWS CLI v2, Bash, jq, and Python should already be available. This preinstalled toolchain is why the rest of the course does not require PowerShell translations.
aws sts get-caller-identityWrite down the Account value and read the Arn. Confirm that this is your training account and expected IAM identity.
export AWS_REGION="ap-south-1"
export AWS_DEFAULT_REGION="$AWS_REGION"
printf "Account: %s\n" "$(aws sts get-caller-identity --query Account --output text)"
printf "Region: %s\n" "$AWS_REGION"Variables, Output, and Queries
Goal
Use environment variables and turn large JSON responses into readable tables and single values.
Estimated time: 15 minutes
Set lab variables
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export LAB_SUFFIX=$(date +%s)
export LAB_PREFIX="cloudshell-lab-${LAB_SUFFIX}"
export BUCKET_NAME="${LAB_PREFIX}-${ACCOUNT_ID}"
printf "ACCOUNT_ID=%s\n" "$ACCOUNT_ID"
printf "LAB_PREFIX=%s\n" "$LAB_PREFIX"
printf "BUCKET_NAME=%s\n" "$BUCKET_NAME"$(command) runs a command and captures its output. ${NAME} expands a variable. Quoting "$NAME" prevents spaces and wildcard characters from being interpreted by Bash.
Compare output formats
# Default JSON output
aws ec2 describe-regions --all-regions
# Human-readable table
aws ec2 describe-regions \
--all-regions \
--query 'Regions[0:5].{Region:RegionName,Status:OptInStatus}' \
--output table
# One value for a script
FIRST_REGION=$(aws ec2 describe-regions \
--all-regions \
--query 'Regions[0].RegionName' \
--output text)
echo "First region returned: $FIRST_REGION"The table should contain only Region and Status. The final command should save one plain-text region name in FIRST_REGION.
Inspect exit status
aws sts get-caller-identity >/dev/null
printf "Successful command status: %s\n" "$?"
aws s3api head-bucket --bucket "this-bucket-should-not-exist-${ACCOUNT_ID}" 2>/dev/null
printf "Failed command status: %s\n" "$?"The successful command returns 0. The missing-bucket check returns a non-zero status. Scripts use this status to decide whether to continue, retry, or stop.
Files and a Reusable Script
Goal
Create a persistent course directory and write a small script that verifies your AWS context.
Estimated time: 10 minutes
mkdir -p "$HOME/aws-course/cloudshell-lab"
cd "$HOME/aws-course/cloudshell-lab"
pwd
ls -lacat > check-context.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-not-set}}"
ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
ARN=$(aws sts get-caller-identity --query Arn --output text)
printf "Account: %s\n" "$ACCOUNT"
printf "Identity: %s\n" "$ARN"
printf "Region: %s\n" "$REGION"
printf "Directory: %s\n" "$PWD"
EOF
chmod +x check-context.sh
./check-context.shThe quoted EOF prevents variables from expanding while the file is created. They expand later when the script runs. set -euo pipefail stops the script on failed commands, unset variables, and failed pipeline stages.
Close and reopen the CloudShell panel, return to ~/aws-course/cloudshell-lab, and confirm that check-context.sh still exists. Environment variables may need to be exported again.
Create, Inspect, and Delete an S3 Resource
Goal
Run a complete AWS CLI workflow: create a resource, verify it, change it, inspect it, and clean it up.
Estimated time: 20 minutes
If you opened a new CloudShell session, restore the variables first:
export AWS_REGION="ap-south-1"
export AWS_DEFAULT_REGION="$AWS_REGION"
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export LAB_SUFFIX=${LAB_SUFFIX:-$(date +%s)}
export LAB_PREFIX="cloudshell-lab-${LAB_SUFFIX}"
export BUCKET_NAME="${LAB_PREFIX}-${ACCOUNT_ID}"
echo "$BUCKET_NAME"Create a private bucket
if [ "$AWS_REGION" = "us-east-1" ]; then
aws s3api create-bucket \
--bucket "$BUCKET_NAME" \
--region "$AWS_REGION"
else
aws s3api create-bucket \
--bucket "$BUCKET_NAME" \
--region "$AWS_REGION" \
--create-bucket-configuration LocationConstraint="$AWS_REGION"
fi
aws s3api put-public-access-block \
--bucket "$BUCKET_NAME" \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=trueThe create command returns the bucket location. The public-access command returns no output on success. No output does not mean the command was skipped.
Upload and inspect an object
cat > hello.txt << EOF
Created from AWS CloudShell
Account: $ACCOUNT_ID
Region: $AWS_REGION
Created: $(date -u +%FT%TZ)
EOF
aws s3 cp hello.txt "s3://$BUCKET_NAME/hello.txt"
aws s3api list-objects-v2 \
--bucket "$BUCKET_NAME" \
--query 'Contents[].{Key:Key,Bytes:Size,Modified:LastModified}' \
--output table
aws s3 cp "s3://$BUCKET_NAME/hello.txt" -The table is produced by --query, while the final command streams the object to standard output because its destination is -.
Inspect configuration
aws s3api get-public-access-block \
--bucket "$BUCKET_NAME" \
--query PublicAccessBlockConfiguration \
--output table
aws s3api get-bucket-location \
--bucket "$BUCKET_NAME"All four public-access settings must be True. Confirm that the bucket location matches the lab region.
Diagnose a Failure
Goal
Read an error, inspect the command context, and fix the cause instead of repeatedly rerunning the same command.
Estimated time: 5 minutes
WRONG_BUCKET="${BUCKET_NAME}-wrong"
aws s3api list-objects-v2 \
--bucket "$WRONG_BUCKET"The command should fail because the bucket name is wrong. Read the error code and operation name before continuing.
printf "Expected bucket: %s\n" "$BUCKET_NAME"
printf "Wrong bucket: %s\n" "$WRONG_BUCKET"
aws s3api head-bucket --bucket "$BUCKET_NAME"
echo "Correct bucket exists"You diagnosed the failure by printing the variables and checking the intended resource. This is safer than blindly repeating a create command.
Cleanup
Run this before leaving
S3 storage in this lab is tiny, but cleanup is part of the course workflow. Verify the bucket name before deleting it.
printf "Deleting s3://%s\n" "$BUCKET_NAME"
aws s3 rm "s3://$BUCKET_NAME" --recursive
aws s3api delete-bucket \
--bucket "$BUCKET_NAME" \
--region "$AWS_REGION"
if aws s3api head-bucket --bucket "$BUCKET_NAME" 2>/dev/null; then
echo "Bucket still exists"
exit 1
else
echo "Cleanup verified: bucket no longer exists"
fi
rm -f "$HOME/aws-course/cloudshell-lab/hello.txt"The verification must print Cleanup verified. Your reusable check-context.sh can remain in the persistent home directory.