从EC2实例中查找区域


131

有没有一种方法可以从实例内部查找实例的区域?

我正在寻找类似于查找实例id的方法的东西。



8
对于任何不在乎所有shell脚本的人来说,简短答案是:从那里获取可用性区域http://169.254.169.254/latest/meta-data/placement/availability-zone并删除最后一个字符。
Sarsaparilla

这回答了你的问题了吗?如何从ec2实例中获取实例ID?
dWinder

Answers:


147

该URL(http://169.254.169.254/latest/dynamic/instance-identity/document)似乎不再起作用。尝试使用时会收到404。我有以下代码,虽然似乎工作:

EC2_AVAIL_ZONE=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
EC2_REGION="`echo \"$EC2_AVAIL_ZONE\" | sed 's/[a-z]$//'`"

希望这可以帮助。

编辑:sed根据评论进行了改进


4
该程序将在EC2实例内部运行,并由AWS后端提供支持。它无法在其他任何地方工作(主要是因为该IP是APIPA)。同样,如果不连接到元数据源,就无法直接从实例内部获取此信息。这假定169.254.169.254 API可用,并且您的脚本应相应地处理网络故障。ec2-metadata只是该API的包装器,但实际上做同样的事情。
dannosaur's

1
有记载吗?您能解释一下如何找到它吗?
meawoppl

2
老实说,当我想出那个2线时,我只是在想API,寻找可以用来识别正确区域的任何东西。AWS的API元数据在这里完全记录:docs.aws.amazon.com/AWSEC2/latest/UserGuide/...
dannosaur

12
sed替换命令比为EC2_REGION提供的命令简单得多:sed 's/[a-z]$//
threejeez

2
如果在启动脚本中,则可能尚未实例化元数据服务-如果是这样,请等待并重试。我已经看到启动后需要10到15秒才能使元数据位置可用。
vacri

81

还有另一种方法可以实现:

REGION=`curl http://169.254.169.254/latest/dynamic/instance-identity/document|grep region|awk -F\" '{print $4}'`

echo $REGION

us-east-1

应该在任何地区/ az(以及任何AMI)上使用吗?我正在404 - Not Found尝试GET从中的计算机访问该URL us-east-1a
亚当·蒙森(2012年

@AdamMonsen可能是暂时错误。我在us-east-1a上,效果很好。
Florin Andrei 2014年

谢谢@FlorinAndrei。现在也对我有用。
亚当·蒙森

3
与jq:curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region
Yaron

4
与awk:curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | awk -F\" '/region/ {print $4}'
Yaron

38

如果可以使用jq,可以运行以下命令:

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq .region -r

我想这是最干净的方法。


31
ec2-metadata --availability-zone | sed 's/.$//'

对于基于debian的系统,该命令不带破折号。

ec2metadata --availability-zone | sed 's/.$//'

6
获取仅包含区域名称的纯字符串:ec2-metadata --availability-zone | sed 's/placement: \(.*\).$/\1/'
nahsh

ec2-metadata似乎不是默认情况下可用的东西-您可以包括安装说明吗?
蒂姆·马龙

23

如果您想避免使用正则表达式,可以使用Python编写以下代码:

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | python -c "import json,sys; print json.loads(sys.stdin.read())['region']"

这个答案应该更高!
Kostas Demiris

@KostasDemiris我同意,与其说是正则表达式,不如说是从JSON结构中读取值。
lasec0203

1
我同意,如果您没有安装jq,这似乎是最好的方法。您真的希望AWS将其公开为169.254.169.254/latest/meta-data/placement/region ...
Krenair

17

您可以使用ec2-metadata:

ec2-metadata -z | grep -Po "(us|sa|eu|ap)-(north|south|central)?(east|west)?-[0-9]+"

2
有了这个,如果您在里面,eu-central-1就会上当了。
dannosaur 2015年

2
central我最初写答案时不存在。现在添加。
Daniel Kuppitz 2015年

22
对我而言,每次AWS添加新区域时都会中断的脚本似乎不是特别强大的解决方案。
瑞安·B·林奇

1
代替grep,awk '{split($2,arr,"-"); print arr[1]"-"arr[2]}'将仅保留AZ名称的前两个组成部分。
dskrvk

@dskrvk如果你只是保持前两个部分,你怎么之间distringuish eu-west-1eu-west-2eu-west-3(也us-west-1us-west-2)@OP:只匹配'[a-z][a-z]-[a-z]*-[0-9][0-9]*'似乎更安全(这是一个基本的正则表达式,可以缩短与扩展RE)。(当前的正则表达式将在该ca区域,该af区域和该me区域上中断)
Gert van den Berg


14

很简单的一个班轮

export AVAILABILITY_ZONE=`wget -qO- http://instance-data/latest/meta-data/placement/availability-zone`
export REGION_ID=${AVAILABILITY_ZONE:0:${#AVAILABILITY_ZONE} - 1}

4
这是两行
基督教徒,

1
但这不适用于us-west-1地区。返回curl: (6) Could not resolve host: instance-data; Name or service not known错误。
SK Venkat

1
@SKVenkat这可能与您的VPC的DNS设置有关...为元数据api使用IP似乎更安全(其他答案的一半也可以这样做)
Gert van den Berg

@GertvandenBerg,我第二个吧..
SK Venkat

9

如果安装了jq,也可以通过以下方式进行处理(可能是最“优雅”的方法):

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -c -r .region

这只是返回“区域”的原始值,而无需任何漂亮的印刷或其他格式。参考:AWS论坛


7

从可用区中获取区域,剥离区域的最后一个字母。

ec2-metadata -z | awk '{print $2}' | sed 's/[a-z]$//'

6

使用JQ:

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region


4

这是我发现的最干净的解决方案:

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document |sed -n 's/  "region" : "\(.*\)"/\1/p'

例如,

export REGION=$(curl -s http://169.254.169.254/latest/dynamic/instance-identity/document |sed -n 's/  "region" : "\(.*\)"/\1/p')

  • 不进行API调用,使用EC2实例元数据
  • 仅使用curl和basic sed,因此不会依赖于不太可能安装的SDK或工具。
  • 不会尝试解析可用区名称,因此,如果AWS更改了AZ /区域名称格式,则无需担心

是的,非常感谢。此结果可以轻松地反序列化为json对象。
dynamiclynk

最后我得到一个逗号。
Craig

4

感谢https://unix.stackexchange.com/a/144330/135640,使用bash 4.2+,我们可以从可用区域中删除最后一个字符:

$ region=`curl -s 169.254.169.254/latest/meta-data/placement/availability-zone`
$ region=${region::-1}
$ echo $region
us-east-1

假设AWS继续对附加到该区域的可用性区域使用单个字符。


5
我们始终能够剥离shell中的最后一个字符:region=${region%?}
David Jones

4

只要您使用ec2.internal作为搜索域,2衬板就可以使用:

az=$(curl -s http://instance-data/latest/meta-data/placement/availability-zone)
region=${az:0:${#az} - 1}

4

对于任何想要使用优质ol powershell进行此操作的人

$var = (curl http://169.254.169.254/latest/dynamic/instance-identity/document | Select-String-Pattern "Zone" | ConvertFrom-Json | Select-Object -ExpandProperty "region")
echo $var

3

或者不要将Ubuntu或此工具作为必备条件,只需执行以下操作:

: "${EBS_VOLUME_AVAILABILITY_ZONE:=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)}"
: ${EBS_VOLUME_REGION:="${EBS_VOLUME_AVAILABILITY_ZONE%%*([![:digit:]])}"}

2
请注意,这仅起作用,因为当前可用区始终是区域名称,并在其后附加小写字母(例如,区域为“ us-west-1”,区域为“ us-west-1a”)。如果Amazon打破了这种模式,则以上逻辑将不再起作用。
马特·索尔尼特

3

如果您使用json,请使用正确的工具。jq在这种情况下功能强大。

# curl -s curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.region'
eu-west-1

3

这适用于eu-central-1以及各个字母区域。(我没有足够的代表来回答上面的sed答案)

ec2-metadata --availability-zone | sed 's/[a-z]$//'

应该是ec2metadata --availability-zone | sed 's/.$//'(没有破折号)
弗拉基米尔·

3

如果您在Windows上运行,则可以使用以下Powershell一线式:

$region=(Invoke-RestMethod "http://169.254.169.254/latest/dynamic/instance-identity/document").region

1

我还在寻找一种从实例中查找区域的解决方案,这是我的纯Bash解决方案:

az=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)
region=${az:0:${#az}-1}

除非在某些地区AZ有两个以上的字母(我不知道)。


0

要查找有关您登录的EC2的信息,可以使用ec2-metadata工具。

您可以通过以下链接安装该工具 安装该工具后,您可以运行

# ec2-metadata -z

找出该地区。

该工具随最新(10.10)个Ubuntu AMI一起安装,


4
这是不正确的。 ec2-metadata -z仅显示可用区域,而不显示区域。
马特·索尔尼特

0

如果您希望使用JS获取区域,则应该可以使用:

meta.request("/latest/meta-data/placement/availability-zone",function(err,data){
        if(err)
                console.log(err);
        else{
                console.log(data);
                str = data.substring(0, data.length - 1);
                AWS.config.update({region:str});
                ec2 = new AWS.EC2();
            }
     });

这是从AWS DOCS找到的映射,以响应元数据API调用,只需修剪最后一个字符即可。

  eu-west-1a :eu-west-1
  eu-west-1b :eu-west-1
  eu-west-1c :eu-west-1
  us-east-1a :us-east-1
  us-east-1b :us-east-1
  us-east-1c :us-east-1
  us-east-1d :us-east-1
  ap-northeast-1a :ap-northeast-1
  ap-northeast-1b :ap-northeast-1
  us-west-1a :us-west-1
  us-west-1b :us-west-1
  us-west-1c :us-west-1
  ap-southeast-1a :ap-southeast-1
  ap-southeast-1b :ap-southeast-1

0

ec2metadata(无破折号)是当前命令,可为您提供有关ec2盒的所有aws托管信息。这是最优雅,最安全的方法。(ec2-metadata是旧的,不再有效的命令。)


这可能取决于您选择的虚拟盒子类型。我坚持使用Linux。
GViz

0

仅使用egrep的方法,该方法可以在大多数Linux实例上运行,而无需安装任何额外的工具。我针对所有当前AWS区域的列表进行了测试,它们都匹配。

curl http://169.254.169.254/latest/meta-data/placement/availability-zone | egrep -o '(\w)+-(\w)+-[0-9]'

REGEX的说明:

  • “(\ w)+”匹配任意数量的字母
  • “-”仅匹配一个破折号
  • “ [0-9]”匹配任何1个数字

如果要将其转换为变量,请执行以下操作:

region=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone | egrep -o '(\w)+-(\w)+-[0-9]')


0

对于sed和curl解决方案,格式似乎有所改变。对我而言

curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | sed -n 's/ "region" : "\(.*\)"[,]/\1/p'

0

自从这些答案中的大多数都已经发布以来,AWS做了一些合理的事情并实现了一条新路径:latest/meta-data/placement/region

这意味着获取该区域应该像

REGION="$(wget -q -O - http://169.254.169.254/latest/meta-data/placement/region)"

0

您可能会使用此curl请求获取实例区域

$ curl http://169.254.169.254/latest/meta-data/placement/region
us-east-1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.