I'm launching an EC2 instance, by invoking ec2-run-instances
from simple a bash script, and want to perform further operations on that instance (e.g. associate elastic IP), for which I need the instance id.
The command is something like ec2-run-instances ami-dd8ea5a9 -K pk.pem -C cert.pem --region eu-west-1 -t c1.medium -n 1
, and its output:
RESERVATION r-b6ea58c1 696664755663 default
INSTANCE i-945af9e3 ami-dd8ea5b9 pending 0 c1.medium 2010-04-15T10:47:56+0000 eu-west-1a aki-b02a01c4 ari-39c2e94d
In this example, i-945af9e3
is the id I'm after.
So, I'd need a simple way to parse the id from what the command returns - how would you go about doing it? My AWK is a little rusty... Feel free to use any tool available on a typical Linux box. (If there's a way to get it directly using EC2-API-tools, all the better. But afaik there's no EC2 command to e.g. return the id of the most recently launched instance.)
To find the most recent AMI for your account, you can search with an AMS SKMS CLI command or use the AMS console details page for relevant VPC: Use the AMS console: Available AMIs are listed on the AMI page in the AMS console. Select from AMIs with names that begin with "customer-".
To view instance metadata, you can only use the link-local address of 169.254. 169.254 to access. Requests to the metadata via the URI are free, so there are no additional charges from AWS. Using the curl tool on Linux or the PowerShell cmdlet Invoke-WebRequest on Windows, you will first create your token.
Completing your correct answer, here is a shell script which creates an instance, runs some commands and deletes the instance. It uses awk in the same way as yours.
#!/bin/sh
# Creates an Amazon EC2 virtual machine (an instance) and runs some
# shell commands on it before terminating it. Just an example.
# Stephane Bortzmeyer <[email protected]>
# Parameters you can set.
# Choose an AMI you like (ami-02103876 is a Debian "lenny")
AMI=ami-02103876
# Create your key pair first, for instance on the Web interface
KEY=test-b
KEYDIR=.
# The user name to use depends on the AMI. "root" is common but check
# the documentation of the AMI.
USERNAME=root
# Needs to be a legal Unix group of commands
COMMANDS="(uname -a; df -h; cat /etc/debian_version)"
MAX_CONNECTS=4
MAX_TESTS=6
# If you want to change from the default region, set the environment
# variable EC2_URL for instance 'export
# EC2_URL=https://ec2.eu-west-1.amazonaws.com' to use the 'eu-west-1'
# region
# Also, be sure your default security group allows incoming SSH.
if [ "${EC2_PRIVATE_KEY}" = "" ] || [ "${EC2_CERT}" = "" ]; then
echo "You need to have X.509 certificate and private key locally, and to set the environment variables EC2_PRIVATE_KEY and EC2_CERT to indicate their locations" 1>&2
exit 1
fi
start=$(ec2-run-instances --key ${KEY} $AMI)
if [ $? != 0 ]; then
echo "Machine did not start" 1>&2
exit 1
fi
AMI_E=$(echo "$start" | awk '/^INSTANCE/ {print $3}')
if [ "$AMI_E" != "$AMI" ]; then
echo "AMI does not match (got $AMI_E instead of $AMI), the machine probably did not start" 1>&2
exit 1
fi
INSTANCE=$(echo "$start" | awk '/^INSTANCE/ {print $2}')
# I do not find a way to block until the machine is ready. We
# apparently have to poll.
OVER=0
TESTS=0
while [ $OVER != 1 ] && [ $TESTS -lt $MAX_TESTS ]; do
description=$(ec2-describe-instances ${INSTANCE})
STATE=$(echo "$description" | awk '/^INSTANCE/ {print $6}')
NAME=$(echo "$description" | awk '/^INSTANCE/ {print $4}')
if [ "$NAME" = "" ]; then
echo "No instance ${INSTANCE} available. Crashed or was terminated." 1>&2
exit 1
fi
if [ $STATE = "running" ]; then
OVER=1
else
# I like bc but 'echo $(( TESTS+=1 ))' should work, too. Or expr.
TESTS=$(echo $TESTS+1 | bc)
sleep 2
fi
done
if [ $TESTS = $MAX_TESTS ]; then
echo "${INSTANCE} never got to running state" 1>&2
ec2-terminate-instances ${INSTANCE}
exit 1
fi
echo "$INSTANCE is running, name is $NAME"
# The SSH server does not seem reachable immediately. We again have to poll
OVER=0
TESTS=0
while [ $OVER != 1 ] && [ $TESTS -lt $MAX_CONNECTS ]; do
ssh -o "StrictHostKeyChecking no" -i ${KEYDIR}/${KEY}.pem ${USERNAME}@$NAME "${COMMANDS}"
if [ $? != 255 ]; then
# It means we connected successfully (even if the remote command failed)
OVER=1
else
TESTS=$(echo $TESTS+1 | bc)
sleep 3
fi
done
if [ $TESTS = $MAX_CONNECTS ]; then
echo "Cannot connect to ${NAME}" 1>&2
fi
ec2-terminate-instances ${INSTANCE}
Ok, at least something like this should work:
instance_id=$(ec2-run-instances ami-dd8ea5a9 [...] | awk '/INSTANCE/{print $2}')
Admittedly I was a bit lazy thinking that it's quicker to ask on SO than to relearn some AWK basics... :-)
Edit: simplified AWK usage as Dennis suggested. Also, using $()
instead of `` for clarity, and got rid of intermediate variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With