Command line 查找没有特定标记的所有Amazon AWS实例

Command line 查找没有特定标记的所有Amazon AWS实例,command-line,amazon-web-services,filter,Command Line,Amazon Web Services,Filter,我试图使用AmazonAWS命令行工具来查找所有没有指定标记的实例 查找带有标记的所有实例非常简单,例如 ec2-describe-instances --filter "tag-key=Name" 但是我如何反转该过滤器以仅返回没有标记“Name”的实例呢?AFAIK直接通过CLI您将无法这样做 根据您使用的语法,我可以猜您使用的是旧的cli。我建议您下载新的CLI并致电 aws ec2描述实例——输出json 从python、ruby或任何脚本语言,您可以根据需要使用适当的正则表达式解析j

我试图使用AmazonAWS命令行工具来查找所有没有指定标记的实例

查找带有标记的所有实例非常简单,例如

ec2-describe-instances --filter "tag-key=Name"

但是我如何反转该过滤器以仅返回没有标记“Name”的实例呢?

AFAIK直接通过CLI您将无法这样做

根据您使用的语法,我可以猜您使用的是旧的cli。我建议您下载新的CLI并致电

aws ec2描述实例——输出json

从python、ruby或任何脚本语言,您可以根据需要使用适当的正则表达式解析json输出过滤
ec2描述实例| grep-v“Name”

:p

这将满足您的要求-在此处查找每个不包含名为“YOUR_KEY_NAME_”标记的实例(第二行筛选器用于不包含名为“NAME”标记的实例):

如果要根据标记的值而不是标记的名称进行筛选,此查询将列出所有不包含名为YOUR_KEY_name_的标记(其值为EXCLUDE_ME)的实例。(第2行列出了未命名为“testbox1”的实例。)

菲利佩是对的。解析输出是唯一的方法,因为AWSAPI不提供此功能,官方AWSCLI也不提供此功能。JSON输出非常可解析,尤其是与旧CLI默认打印的多行文本记录相比


API本身返回JSON,新的awscli将JSON打印为默认输出格式。“jq”程序在解析它时非常有用,甚至在发送到终端时会着色,或者您可以输出文本以将其还原为字符串。

我也遇到了同样的问题,我找到了如何查询标记值的方法 您很可能为所有实例定义了相同的标记键;我已经在我的所有实例上定义了一个标记键“MachineName”,我想根据标记键名称的值进行筛选

下面是要筛选的示例,其中名称=Machine1

使用该选项

--filters "Name=tag-key,Values=MachineName" "Name=tag-values,Values=Machine1"

这对我来说很好

不幸的是,底层api调用不支持反向标记过滤,因此CLI也不支持。但是,您可以使用执行搜索的
--query
参数执行客户端过滤。这将使您不必像user2616321的回答那样使用管道

例如:

aws ec2 describe-instances --query "Reservations[].Instances[?Tags[?Key == 'Name']][]"

.InstanceId
添加到该命令的末尾,以便只获取实例ID。

我也完全震惊于通过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)
#/usr/bin/env ruby
需要“json”
#我们将输出任何不包含所有这些标记的实例
所需的_标记=如果ARGV.empty?
%w(姓名)
其他的
ARGV
结束
#将每个实例/保留要输出的键放在此处
保留密钥=%w(所有者ID请求者ID)
实例密钥=%w(标记InstanceId InstanceType PublicDnsName启动时间PrivateIpAddress密钥名)
实例\u不带\u标记=[]
#只需在此处使用CLI即可避免AWS依赖关系
reservations=JSON.parse(
`AWSEC2描述实例`
)[“保留”]
#预订是对启动实例的单个调用。你可能会
#在预订中有多个实例,但通常只有一个是
#一次旋转,意味着每个预订只有一个实例。
预订。每个人都做预订|
保留[“实例”]。每个都有|实例|
#筛选没有所需标记的实例
tag|keys=instance[“Tags”].map{t|t[“Key”]}
除非(标记键和所需标记)。长度==所需标记。长度

不带_标记的实例您可以使用jmespath(驱动
--query
参数的引擎)执行此操作,不管其他人怎么说:

aws ec2 describe-instances \
  --query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | []'
来源:.

由于
--filters
参数似乎不支持反向过滤,下面是我使用
--query
参数解决此问题的方法:

aws ec2 describe-instances \
--query 'Reservations[].Instances[?!contains(Tags[].Key, `Name`)][].InstanceId'
它查看每个实例的标记键数组,并过滤数组中没有标记“Name”的实例。然后将输出展平到实例ID数组

  • 与前面的一些答案相比,它的优点是:无需使用
    jq
    或其他命令来过滤输出
  • 相对于真正的逆过滤器的缺点:在大量实例中可能会慢得多

我使用这个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)

这个评论并没有回答这个问题。此外,像这样一个简单的命令无法提供一个您将用于此的JMESPath的示例?当然,我将简要介绍它。。。当我运行该版本时,我似乎只得到包含“Name”标记的实例-相当于
--filter“tag key=Name”
。问题与此相反,这里有一个非常有用的JQ tidibt,我一直在寻找解决方法。谢谢,对于那些在查找如何删除by==标记而不是删除by时不知何故来到这里的人=标签,(嗯哼),你可以试试这个:你确定过滤器是服务器端的而不是客户端的吗?实际发出的请求是什么?@CraigRinger它绝对是客户端。DescribeInstances api允许服务器端筛选器(aws cli:
--filters
),但缺少“not”功能。因此,所有这些都被本地拉下来,并使用jmespath进行过滤。您可以在aws cli上使用
--debug
,查看它对API的实际调用。感谢您的确认。啊。过滤器API缺少任何形式的
aws ec2 describe-instances \
--query 'Reservations[].Instances[?!contains(Tags[].Key, `Name`)][].InstanceId'
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)