我想在作为 EC2 实例的主机上运行一些脚本,但我不知道如何确定该主机确实是一个 EC2 实例。
我做了一些测试,但这还不够:
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 在评论中提到这一点)
Jos*_*idt 37
首先,我觉得有必要发布一个新的答案,因为现有答案存在以下微妙的问题,并且在收到关于我对 @qwertzguy 的答案的评论的问题后。以下是当前答案的问题:
hostname -d用于内部 DNS的 VPC 名称,而不是其中包含“amazonaws.com”的任何名称。)instance-data.ec2.internalDNS 查找可能不起作用。在我刚刚测试的 Ubuntu EC2 VPC 实例上,我看到:
$ curl http://instance-data.ec2.internal
curl: (6) Could not resolve host: instance-data.ec2.internal
这会导致依赖此方法的代码错误地断定它不在 EC2 上!dmidecode可能有效,但取决于您 a.)dmidecode在您的实例上可用,并且 b.)sudo在您的代码中具有 root 或无密码能力。bios_version的1.0。这个文件根本没有记录在亚马逊的 doc 上,所以我真的不会依赖它。whois在结果上使用在几个级别上存在问题。请注意,该答案中建议的 URL 现在是 404 页面!即使您确实找到了有效的 3rd 方服务,它也会相对非常慢(与在本地检查文件相比)并且可能会遇到速率限制问题或网络问题,或者您的 EC2 实例甚至可能没有外部网络访问。-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 实例上运行的最佳方法是考虑您链接的文档中列出的不同可能性。
小智 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)
小智 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)
主机名可能会更改,针对您的公共 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 中的 Linux 主机,并且不需要网络和任何相关超时:
grep -q amazon /sys/devices/virtual/dmi/id/bios_version
这是有效的,因为亚马逊这样定义这个条目:
$ cat /sys/devices/virtual/dmi/id/bios_version
4.2.amazon
| 归档时间: |
|
| 查看次数: |
33863 次 |
| 最近记录: |