我正在尝试使用 Amazon AWS 命令行工具来查找所有没有指定标签的实例。
查找带有标签的所有实例很简单,例如
ec2-describe-instances --filter "tag-key=Name"
但是我将如何反转该过滤器以仅返回没有标签“名称”的实例?
我正在尝试使用 Amazon AWS 命令行工具来查找所有没有指定标签的实例。
查找带有标签的所有实例很简单,例如
ec2-describe-instances --filter "tag-key=Name"
但是我将如何反转该过滤器以仅返回没有标签“名称”的实例?
你可以用 jmespath (驱动--query
参数的引擎)来做到这一点,不管别人怎么说:
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | []'
这将满足您的要求 - 查找每个不包含名为“YOUR_KEY_NAME_HERE”的标签的实例(第二行过滤器用于没有名为“Name”的标签的实例):
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "YOUR_KEY_NAME_HERE"} ]}) | not)'
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"} ]}) | not)'
如果您想过滤标签的值,而不是标签的名称,此查询将列出不包含名为 YOUR_KEY_NAME_HERE 且值为 EXCLUDE_ME 的标签的所有实例。(第二行列出了未命名为“testbox1”的实例。)
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "YOUR_KEY_NAME_HERE"}, {Value: "EXCLUDE_ME"}]}) | not)'
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"}, {Value: "testbox1"}]}) | not)'
费利佩是正确的。解析输出是唯一的方法,因为 AWS API 不提供此功能,任何官方 AWS CLI 也不提供。JSON 输出非常易于解析,尤其是与旧 CLI 默认打印的多行文本记录相比。
http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html
API 本身返回 JSON,新的 awscli 将该 JSON 打印为其默认输出格式。“jq”程序对解析它非常有用,甚至在发送到终端时会着色,或者您可以 --output text 将其还原为字符串。
由于--filters
参数似乎不支持反向过滤,这是我使用--query
参数解决此问题的方法:
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!contains(Tags[].Key, `Name`)][].InstanceId'
它查看每个实例的标签键数组,并过滤那些在数组中没有标签“名称”的实例。然后将输出展平为实例 ID 数组。
jq
或其他命令来过滤输出。我遇到了同样的问题,我想出了如何查询标签值,您很可能会为所有实例定义相同的标签键;我已经在我的所有实例上定义了一个标签键“MachineName”,我想按标签键名称的值进行过滤
下面是过滤 Name=Machine1 的示例
使用选项
--filters "Name=tag-key,Values=MachineName" "Name=tag-values,Values=Machine1"
这对我来说很好
不幸的是,底层 api 调用DescribeInstances不支持反向标签过滤,因此 CLI 也不支持。但是,您可以使用执行JMESPath搜索的--query
参数进行客户端过滤。这将防止您不得不像 user2616321 的回答那样使用管道。
例如:
aws ec2 describe-instances --query "Reservations[].Instances[?Tags[?Key == 'Name']][]"
添加.InstanceId
到最后以获取实例ID。
AFAIK 直接通过 CLI 你将无法做到这一点。
根据您使用的语法,我猜您使用的是旧的 cli。我建议您下载新的 CLI http://aws.amazon.com/cli/并调用
aws ec2 describe-instances --output json
从 python、ruby 或任何脚本语言,您可能希望根据需要使用适当的正则表达式解析 json 输出过滤
我使用这个 python3 / boto 脚本进行非常大的反向标签过滤操作:
import boto3
from botocore.config import Config
# Attempts
config = Config(
retries = dict(
max_attempts = 3
)
)
# Tag(s)
my_tags = [
{
"Key": "backup",
"Value": "true"
}
]
# Owner ID Filter
owner_id = 'SOME_OWNER_ID'
# Connection
ec2 = boto3.client("ec2", config=config)
# Instances
def tag_instances():
# All Reservations [instances] (tagged or untagged)
all_reservations = ec2.describe_instances(Filters = [{'Name': 'owner-id', 'Values':[owner_id]}])
# Append each InstanceId in all_reservations to all_instances
all_instances = []
for all_reservation in all_reservations['Reservations']:
for all_instance in all_reservation['Instances']:
all_instances.append(all_instance['InstanceId'])
# Append each InstanceId with backup:true or backup:false to tagged_instances
tagged_reservations = ec2.describe_instances(Filters = [{'Name': 'owner-id', 'Values':[owner_id]},{'Name': 'tag:backup', 'Values':['true','false']}])
tagged_instances = []
for tagged_reservation in tagged_reservations['Reservations']:
for tagged_instance in tagged_reservation['Instances']:
tagged_instances.append(tagged_instance['InstanceId'])
# Append each InstanceId in all_instances and not in tagged_instances to untagged_instances
untagged_instances = [all_instance for all_instance in all_instances if all_instance not in tagged_instances]
# Print untagged InstanceId
print("untagged_instanceids:",untagged_instances)
我也对通过 CLI 执行此操作的难度感到震惊。我喜欢 user2616321 的回答,但我在让它输出每个实例所需的确切字段时遇到了一些麻烦。在花了一段时间在查询语法中弄乱并使用 JMESPath 失败后,我最终只制作了一个小 ruby 脚本来执行此操作。如果有人想节省几分钟写自己的时间,这里是:
#!/usr/bin/env ruby
require 'json'
# We'll output any instance that doesn't contain all of these tags
desired_tags = if ARGV.empty?
%w(Name)
else
ARGV
end
# Put the keys we want to output per instance/reservation here
reservation_keys = %w(OwnerId RequesterId)
instance_keys = %w(Tags InstanceId InstanceType PublicDnsName LaunchTime PrivateIpAddress KeyName)
instances_without_tags = []
# Just use CLI here to avoid AWS dependencies
reservations = JSON.parse(
`aws ec2 describe-instances`
)["Reservations"]
# A reservation is a single call to spin up instances. You could potentially
# have more than one instance in a reservation, but often only one is
# spun up at a time, meaning there is a single instance per reservation.
reservations.each do |reservation|
reservation["Instances"].each do |instance|
# Filter instances without the desired tags
tag_keys = instance["Tags"].map { |t| t["Key"] }
unless (tag_keys & desired_tags).length == desired_tags.length
instances_without_tags <<
reservation.select { |k| reservation_keys.include?(k) }.
merge(instance.select { |k| instance_keys.include?(k) })
end
end
end
puts JSON.pretty_generate(instances_without_tags)
你总是可以这样做
ec2-describe-instances | grep -v "Name"
::p