使用ec2-api-tools获取新启动实例的ID

19
我正在通过调用简单的bash脚本中的ec2-run-instances启动EC2实例,并希望对该实例执行进一步操作(例如关联弹性IP),为此我需要实例ID。

命令类似于ec2-run-instances ami-dd8ea5a9 -K pk.pem -C cert.pem --region eu-west-1 -t c1.medium -n 1,其输出:
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   

在这个例子中,i-945af9e3 是我需要的 id。
因此,我需要一种简单的方法从命令返回的内容中解析出该 id - 你会怎样做?我的 AWK 工具有点生疏...请随意使用任何一个典型 Linux 系统上可用的工具。(如果有一种直接使用 EC2-API 工具获取它的方法,那就更好了。但据我所知,没有 EC2 命令可以返回最近启动实例的 id。)
5个回答

22

补充你的正确答案,这是一个shell脚本,它创建一个实例,运行一些命令并删除该实例。它使用和你的方式相同的awk。

#!/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 <stephane+amazon@bortzmeyer.org>

# 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}

12

好的,至少这样做应该可以:

instance_id=$(ec2-run-instances ami-dd8ea5a9 [...] | awk '/INSTANCE/{print $2}') 

坦白说,我有点懒,认为向SO提问比重新学习一些AWK基础更快... :-)

编辑:像Dennis建议的那样简化了AWK的用法。此外,为了清晰起见,使用$()代替``,并且摆脱了中间变量。


2
不需要使用 grepawk '/INSTANCE/{print $2}' - Dennis Williamson
1
谢谢@Dennis - 现在看起来干净了一些。 - Jonik
我无法在Ubuntu bash中让您的awk工作。instance_id=$((ec2-run-instances ami-2b0b1442 -O aws-access-key-id -W aws-secret-access-key -k my-key -g default -t m1.small | awk '/INSTANCE/{print $2}') | awk '/INSTANCE/{prin $2}') ; echo $instance_id >> ~/instance_id.txt - Dennis
我看到打印错误,编辑超时,无法完成。同时发现在注释中不允许使用<RETURN>键。 - Dennis
当我使用下面的“egrep和cut”命令进行替换时,它可以正常工作。 - Dennis

9
作为ec2-run-instances的替代方案,您可以使用awscli run-instances一行代码创建一个ec2实例并获取InstanceId:
export MyServerID=$(aws ec2 run-instances --image-id AMI --count 1 --instance-type t2.micro --key-name "my_ssh_key" --security-group-ids sg-xxx --subnet-id subnet-yyy --query 'Instances[0].InstanceId' --output text)

3

不需要使用awk:

# create the instance and capture the instance id
echo "Launching instance..."
instanceid=$(ec2-run-instances --key $pemkeypair --availability-zone $avzone $ami | egrep ^INSTANCE | cut -f2)
if [ -z "$instanceid" ]; then
    echo "ERROR: could not create instance";
    exit;
else
    echo "Launched with instanceid=$instanceid"
fi

来源于http://www.hulen.com/post/22802124410/unattended-amazon-ec2-install-script

这是一个Amazon EC2无人值守安装脚本,可用于一键式部署云服务器。该脚本自动安装和配置必要的软件包,并设置SSH访问和防火墙规则。您只需要将脚本下载到您的EC2实例并执行即可。在执行期间,您可以使用screen命令进行会话管理。

-1
http://www.tothenew.com/blog/how-to-parse-json-by-command-line-in-linux/
best tool to parse json in shell

#get instance id 
cat sample.json | jq '.Instances[0].InstanceId'|sed -e 's/^"//' -e 's/"$//' 
#check instances is running or not 
cat status.json | jq '.InstanceStatuses[0].InstanceState.Name'|sed -e 's/^"//' -e 's/"$//' 

欢迎提供潜在解决方案的链接,但请添加链接周围的上下文,以便其他用户了解它是什么以及为什么存在。在引用重要链接的最相关部分时,请始终考虑到目标站点无法访问或永久离线的情况。请注意,作为“几乎只是指向外部网站的链接”是为什么会删除某些答案?的可能原因之一。 - Tunaki
#获取实例id cat sample.json | jq '.Instances[0].InstanceId'|sed -e 's/^"//' -e 's/"$//' #检查实例是否正在运行 cat status.json | jq '.InstanceStatuses[0].InstanceState.Name'|sed -e 's/^"//' -e 's/"$//' - Aakash Kag
要运行上述命令,请安装jq,然后将JSON响应保存到文件中,然后尝试... jq的安装链接已在我的答案中分享。 - Aakash Kag
请修改您的回答并加入这些信息,而不是发布评论。 - Tunaki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接