如何知道机器是否是 EC2 实例

Kel*_*dil 51 amazon-ec2

我想在作为 EC2 实例的主机上运行一些脚本,但我不知道如何确定该主机确实是一个 EC2 实例。

我做了一些测试,但这还不够:

  • 测试二进制 ec2_userdata 是否可用(但这并不总是正确的)
  • 测试“ http://169.254.169.254/latest/meta-data ”的可用性(但这是否总是正确的?这个“神奇IP”是什么?)

qwe*_*guy 45

更改 Hannes 的回答以避免错误消息并在脚本中包含示例用法:

if [ -f /sys/hypervisor/uuid ] && [ `head -c 3 /sys/hypervisor/uuid` == ec2 ]; then
    echo yes
else
    echo no
fi
Run Code Online (Sandbox Code Playgroud)

这在 Windows 实例中不起作用。与 curl 相比的优势在于它在 EC2 和非 EC2 上都接近瞬时。

更新:对于新C5 / M5的情况下,使用的文件/sys/devices/virtual/dmi/id/product_uuid,而不是和检查EC2 代替ec2。(感谢 Josh 和 Saumitra 在评论中提到这一点)

  • 危险!这种方法多年来一直为我们可靠地工作......直到最近,最新的 c5 和 m5 类型**不存在此文件**。所以我必须添加一个 http://169.254.169.254/ 的回退检查来处理这些实例。 (8认同)
  • AWS 似乎也建议这样做 http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html (6认同)
  • 我喜欢这个方法。请注意,在虚拟机管理程序下运行的非 EC2 系统可能会生成以“ec2”开头的 UUID —— 误报。这不太可能(256 分之一的机会),并且仅当您使用填充该文件的管理程序时。这就是为什么上面链接的文档说“您*可能*正在查看一个 EC2 实例”。 (3认同)
  • 对于获得此答案的读者,新的 C5/M5 系列没有`/sys/hypervisor/uuid`(至少在最新的 AMI 上)在@Mike 的链接 https://docs.aws.amazon 中使用第二个替代方案。 com/AWSEC2/latest/UserGuide/identify_ec2_instances.html 即使用`/sys/devices/virtual/dmi/id/product_uuid`或dmidecode (3认同)
  • @Wildcard:我无法编辑我的评论,但没错。 (2认同)

Jos*_*idt 37

首先,我觉得有必要发布一个新的答案,因为现有答案存在以下微妙的问题,并且在收到关于我对 @qwertzguy 的答案的评论的问题后。以下是当前答案的问题:

  1. 接受的答案从@MatthieuCerda绝对不可靠地工作,至少不是我签反对任何VPC实例。(在我的实例中,我获得了hostname -d用于内部 DNS的 VPC 名称,而不是其中包含“amazonaws.com”的任何名称。)
  2. 最高的投票答案从@qwertzguy做新M5或C5情况下不工作,不具有此文件。亚马逊忽略记录此行为更改 AFAIK,尽管有关此主题的文档页面确实说“...如果/sys/hypervisor/uuid 存在...”。我询问 AWS 支持人员此更改是否是故意的,请参见下文 †。
  3. @Jer答案不一定适用于所有地方,因为instance-data.ec2.internalDNS 查找可能不起作用。在我刚刚测试的 Ubuntu EC2 VPC 实例上,我看到: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal 这会导致依赖此方法的代码错误地断定它不在 EC2 上!
  4. 来自@tamale的答案dmidecode可能有效,但取决于您 a.)dmidecode在您的实例上可用,并且 b.)sudo在您的代码中具有 root 或无密码能力。
  5. 回答检查/ SYS /设备/虚拟/ DMI / ID / bios_version从@spkane是危险的误导!我查了一个Ubuntu的14.04 M5例如,找来bios_version1.0。这个文件根本没有记录在亚马逊的 doc 上,所以我真的不会依赖它。
  6. @Chris-Montanaro答案的第一部分检查不可靠的 3rd-party URL 并whois在结果上使用在几个级别上存在问题。请注意,该答案中建议的 URL 现在是 404 页面!即使您确实找到了有效的 3rd 方服务,它也会相对非常慢(与在本地检查文件相比)并且可能会遇到速率限制问题或网络问题,或者您的 EC2 实例甚至可能没有外部网络访问。
  7. @Chris-Montanaro答案中的第二个建议检查http://169.254.169.254/稍微好一点,但另一位评论者指出其他云提供商提供此实例元数据 URL,因此您必须小心避免错误积极的一面。此外,它仍然比本地文件慢得多,我已经看到此检查在重载实例上特别慢(返回几秒钟)。此外,您应该记住将 a -mor--max-time参数传递给 curl 以避免它挂起很长时间,尤其是在非 EC2 实例上,该地址可能会导致无处和挂起(如@algal 的回答)。

此外,我没有看到有人提到亚马逊记录的检查(可能的)文件的后备/sys/devices/virtual/dmi/id/product_uuid

谁知道确定您是否在 EC2 上运行会如此复杂?!好的,既然我们已经列出了列出的方法的(大部分)问题,这里有一个建议的 bash 片段来检查您是否在 EC2 上运行。我认为这通常适用于几乎所有 Linux 实例,Windows 实例是读者的练习。

#!/bin/bash

# This first, simple check will work for many older instance types.
if [ -f /sys/hypervisor/uuid ]; then
  # File should be readable by non-root users.
  if [ `head -c 3 /sys/hypervisor/uuid` == "ec2" ]; then
    echo yes
  else
    echo no
  fi

# This check will work on newer m5/c5 instances, but only if you have root!
elif [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
  # If the file exists AND is readable by us, we can rely on it.
  if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "EC2" ]; then
    echo yes
  else
    echo no
  fi

else
  # Fallback check of http://169.254.169.254/. If we wanted to be REALLY
  # authoritative, we could follow Amazon's suggestions for cryptographically
  # verifying their signature, see here:
  #    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
  # but this is almost certainly overkill for this purpose (and the above
  # checks of "EC2" prefixes have a higher false positive potential, anyway).
  if $(curl -s -m 5 http://169.254.169.254/latest/dynamic/instance-identity/document | grep -q availabilityZone) ; then
    echo yes
  else
    echo no
  fi

fi
Run Code Online (Sandbox Code Playgroud)

显然,您可以通过更多的回退检查来扩展它,并包括关于处理的偏执,例如从/sys/hypervisor/uuid偶然的“ec2”开始的误报等等。但这对于说明目的来说是一个足够好的解决方案,并且可能几乎所有非病理性用例。

[†] 从 AWS 支持那里得到了关于 c5/m5 实例更改的解释:

C5 和 M5 实例使用新的管理程序堆栈,并且相关的内核驱动程序不会像其他/较旧的实例类型使用的 Xen 驱动程序那样在 sysfs(挂载在 /sys)中创建文件。检测操作系统是否在 EC2 实例上运行的最佳方法是考虑您链接文档中列出的不同可能性。

  • 是的,2018 年的旅伴……这就是您一直在寻找的答案。 (5认同)

小智 15

通过 EC2 内部域名而不是 IP 查找元数据,如果您不在 EC2 上,这将返回快速 DNS 故障,这可以避免 IP 冲突和路由问题:

curl -s http://instance-data.ec2.internal && echo "EC2 instance" || echo "Non EC2 instance"
Run Code Online (Sandbox Code Playgroud)

在某些发行版中,非常基本的系统或安装阶段的早期curl不可用。使用wget代替:

wget -q http://instance-data.ec2.internal && echo "EC2 instance" || echo "Non EC2 instance"
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,在 VPC 中似乎失败了! (5认同)
  • 也不要在双引号内使用感叹号字符——你的回声 [可能会爆炸](http://serverfault.com/questions/208265/what-is-bash-event-not-found) 和 `-bash : !": event not found`。用单引号代替那些 `echo`。 (2认同)

小智 14

如果目标是判断它是 EC2 实例还是其他类型的云实例,例如 google,那么dmidecode工作非常好并且不需要网络。与其他一些方法相比,我喜欢这种方法,因为 EC2 和 GCE 的元数据 url 路径不同。

# From a google compute VM
$ sudo dmidecode -s bios-version
Google

# From an amazon ec2 VM
$ sudo dmidecode -s bios-version
4.2.amazon
Run Code Online (Sandbox Code Playgroud)


Chr*_*aro 6

主机名可能会更改,针对您的公共 IP 运行 whois:

if [[ ! -z $(whois $(curl -s shtuff.it/myip/short) | grep -i amazon) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi
Run Code Online (Sandbox Code Playgroud)

或点击 AWS 元数据网址

if [[ ! -z $(curl -s http://169.254.169.254/1.0/) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi
Run Code Online (Sandbox Code Playgroud)

  • 如果您不在 EC2 上运行,则将 --connect-timeout 1 添加到第二个 curl 语句以快速失败。 (2认同)

spk*_*ane 5

这也适用于 ec2 中的 Linux 主机,并且不需要网络和任何相关超时:

grep -q amazon /sys/devices/virtual/dmi/id/bios_version

这是有效的,因为亚马逊这样定义这个条目:

$ cat /sys/devices/virtual/dmi/id/bios_version 4.2.amazon