Bash script to loop through output from AWS Command Line Client - bash

I'm getting a list of EC2 instances and then trying to loop through them but for some reason I'm not able to get the loop to work.
output="$(aws ec2 describe-instances --filters 'Name=tag:Environment,Values=development' --query '[Reservations[*].Instances[*].PublicDnsName]' --output text)"
echo $output displays something like:
ec2-55-55-555-555.eu-west-1.compute.amazonaws.com
ec2-66-66-666-666.eu-west-1.compute.amazonaws.com
Then I create an array like this:
instances=(${output//'\n'/ })
echo ${instances[0]} and echo ${instances[1]} gives the correct output.
And then try to iterate through the array:
for i in $instances; do echo instance: "$i"; done
But I get:
instance: ec2-55-55-555-555.eu-west-1.compute.amazonaws.com
ec2-66-66-666-666.eu-west-1.compute.amazonaws.com
Instead of:
instance: ec2-55-55-555-555.eu-west-1.compute.amazonaws.com
instance: ec2-66-66-666-666.eu-west-1.compute.amazonaws.com
What am I doing wrong? And is there a better way to loop through the results, maybe rather using the json output format?

I am not sure if you got an answer for this question. Will this help?
for dns in $(aws ec2 describe-instances --region ap-northeast-1 --query 'Reservations[*].Instances[*].PublicDnsName' --output text) ; do echo $dns ; done

For windows cli:
aws ec2 describe-instances --query "Reservations[].Instances[].InstanceId" > instances
FOR /f %i IN (instances) DO aws ec2 terminate-instances --instance-ids %i

This also works for me, add it to a bash array:
for instance in $(aws ec2 describe-instances --filters "Name=tag:Application,Values=yourValue" "Name=tag:Environment,Values=development" --query 'Reservations[*].Instances[*].InstanceId' --output text); do envInstances+=(${instance}); done
for i in ${envInstances[#]}; do echo "hello $i"; done
hello i-instance1
hello i-instance12
hello i-instance16

Not sure if you just gave up, but in BASH, better to just do this:
OUTPUT=($(aws ec2 describe-instances --filters
'Name=tag:Environment,Values=development' --query
'[Reservations[].Instances[].PublicDnsName]' --output text))
then (if you want a count)
echo "${#OUTPUT[#]} instances found."
Good luck!

Related

how to iterate over aws cli result using bash for loop ? [describe-images]

Goal: find specific AMI's and copy them to another AWS region.
using describe-images and its filter i get a list of ImageId and Name,
AMI_LIST=$(aws ec2 describe-images --filters "Name=tag:Name,Values=*one*,*two*,*three*,*four*" \
"Name=state,Values=available" "Name=tag:Name,Values=${CUSTOMER_NAME}*" \
--query 'Images[*].{ID:ImageId,NAME:Name}' --output text)
echo $AMI_LIST
result:
ami-036ba4ef9fa1d148d big394_one_1 ami-06d13684f11138f1f big394_two_3 ami-0706803a11e21946d big394_two_1 ami-094043f896db39243 big394_two_2 ami-0c11ff60c981c2273 big394_three_1 ami-0d0b30fcc69f30af8 big394_four_1
then i want to copy the images to another AWS region using a loop:
for ami in $AMI_LIST; do
aws ec2 copy-image --source-image-id ${ami[0]} --source-region us-east-1 --region us-west-2 --name ${ami[2]}
done
ofc it does not work because ${ami[0]} and ${ami[1]} has no meaning, but they represent what i would like to achieve.
i did try to play with converting the list to array but without success.
Thanks.
This should achieve what you expected :
aws ec2 describe-images --filters "Name=tag:Name,Values=*one*,*two*,*three*,*four*" \
"Name=state,Values=available" "Name=tag:Name,Values=${CUSTOMER_NAME}*" \
--query 'Images[*].{ID:ImageId,NAME:Name}' --output text \
| while read ami name; do
aws ec2 copy-image --source-image-id $ami --source-region us-east-1\
--region us-west-2 --name $name
done

For Loop variable in Bash Script [duplicate]

This question already has answers here:
How can I loop over the output of a shell command?
(4 answers)
Closed 1 year ago.
I am trying to execute this script as bash test.sh
#!/bin/bash
for region in "aws ec2 describe-regions --output text | cut -f4";
do
echo -e "\nListing Instances in region:'$region'...";
aws ec2 describe-instances --region $region;
done
But the only output that I get for $region is the print of the command. so it says
"Listing Instances aws ec2 describe-regions .. "
How can I fix this ?
You aren't executing a command; you are iterating over a sequence containing exactly one element, the strings aws ec2 ...
You need a command substitution to actually execute the command:
for region in $(aws ec2 describe-regions --output text | cut -f4); do
echo -e ...
aws ec2 describe-instances --region "$region"
done

get subnet id AWS

i am trying to get the subnet ids within a particular VPC and store them in variables
so I can use them in a bash script
aws ec2 describe-subnets --filter "Name=vpc-id,Values=VPCid" --region $REGION --query "Subnets[*].SubnetId" --output text
and this gives something like this
subnet-12345 subnet-78910
(END)
I wonder how I can store them into a variable.
I tried with
SBnet=$(aws ec2 describe-subnets --filter "Name=vpc-id,Values=VPCid" --region $REGION --query "Subnets[*].SubnetId" --output text)
but then I do not know I can access the array/list created.
I tried with
echo $(SBnet[0])
but does not work
I am on MACos usin zsh
You can do this as follows (add your VPC and the region):
#!/bin/bash
SUBNET_IDS=$(aws ec2 describe-subnets --filter "Name=vpc-id,Values=vpc-1234" --query "Subnets[*].SubnetId" --output text)
for SUBNET_ID in $SUBNET_IDS;
do
echo $SUBNET_ID
done
To split the list of subnet IDs into variables, you can do this:
#!/bin/bash
SUBNET_IDS=$(aws ec2 describe-subnets --filter "Name=vpc-id,Values=vpc-1234" --query "Subnets[*].SubnetId" --output text)
IFS=$'\t ' read -r -a subnet_ids <<< $SUBNET_IDS
echo "${subnet_ids[0]}"
echo "${subnet_ids[1]}"
And the individual subnet IDs will be in the subnet_ids array.
you can do as #jarmod suggested and you could also write a query to extract all the subnets tied to all the VPC's in your system in a comma separated output and use it further like this
aws ec2 describe-subnets --query "Subnets[].[SubnetId,VpcId,CidrBlock,AvailabilityZone]" --output text|sed 's/\t/,/g'

AWS cli: how to start all machines found by tag

I can list all machines:
aws ec2 describe-instances --filters "Name=tag:Env,Values=my_super_tag" --query 'Reservations[].Instances[].[InstanceId]' --output text
And then I wish to start all found machines - is the aws cli expression what allow that?
The workaround can be applying next aws cli command for received output (machines ids) but here I got the problem too:
$ aws ec2 describe-instances --filters "Name=tag:Env,Values=my_super_tag" --query 'Reservations[].Instances[].[InstanceId]' --output text\
| xargs -L1 aws ec2 start-instances --instance-ids
' does not existd (InvalidInstanceID.NotFound) when calling the StartInstances operation: The instance ID 'i-12345677890
xargs: aws: exited with status 255; aborting
Strange because with echo
aws ec2 describe-instances --filters "Name=tag:Env,Values=spt1" --query 'Reservations[].Instances[].[InstanceId]' --output text | xargs -L 1 echo aws ec2 start-instances --instance-ids
I get output (executing one of below line works as intended)
aws ec2 start-instances --instance-ids i-2123456789
aws ec2 start-instances --instance-ids i-3123456789
aws ec2 start-instances --instance-ids i-4123456789
aws ec2 start-instances --instance-ids i-5123456789
You can embed one command within another, eg:
aws ec2 start-instances --instance-ids `ANOTHER-COMMAND`
So, try this:
aws ec2 start-instances --instance-ids `aws ec2 describe-instances --filters "Name=tag:Env,Values=my_super_tag" --query 'Reservations[].Instances[].InstanceId' --output text`
#John Rotenstein answer do the job, but due to AWS limits and handling already started instances (my question about this link), it's good to add to query
"Name=instance-state-name,Values=stopping,stopped"
So full query then will look like
aws ec2 start-instances --instance-ids `aws ec2 describe-instances --filters "Name=tag:Env,Values=my-super-tag" "Name=instance-state-name,Values=stopping,stopped" --query 'Reservations[].Instances[].InstanceId' --outpu t text`

List public IP addresses of EC2 instances

I want to list the public IP addresses of my EC2 instances using Bash, separated by a delimiter (space or a new-line).
I tried to pipe the output to jq with aws ec2 describe-instances | jq, but can't seem to isolate just the IP addresses.
Can this be done by aws alone, specifying arguments to jq, or something else entirely?
Directly from the aws cli:
aws ec2 describe-instances \
--query "Reservations[*].Instances[*].PublicIpAddress" \
--output=text
Filter on running instances (you can drop that part if you don't need it)
Query for each PublicIPaddress and the Name Tag, handling when Name isn't set
aws ec2 describe-instances \
--filter "Name=instance-state-name,Values=running" \
--query "Reservations[*].Instances[*].[PublicIpAddress, Tags[?Key=='Name'].Value|[0]]" \
--output text
The below command would list the IP addresses of all your running EC2 instances
aws ec2 describe-instances | grep PublicIpAddress | grep -o -P "\d+\.\d+\.\d+\.\d+" | grep -v '^10\.'
Hope that answers your query...
But this works without all the errors about access:
wget -qO- http://instance-data/latest/meta-data/public-ipv4/|grep .
You can use instance metadata so you can run the following command from the ec2 instance:
curl http://169.254.169.254/latest/meta-data/public-ipv4
and it will give you the public IP of the instance. If you want the private IP, you will run
curl http://169.254.169.254/latest/meta-data/local-ipv4
aws ec2 describe-instances --query "Reservations[].Instances[][PublicIpAddress]"
Refer:
http://docs.aws.amazon.com/cli/latest/userguide/controlling-output.html

Resources