如何使用CLI删除AWS S3中的版本化存储桶?

Nob*_*ift 41 command-line-interface amazon-s3 amazon-web-services s3cmd aws-cli

我试过了两个s3cmd:

$ s3cmd -r -f -v del s3://my-versioned-bucket/
Run Code Online (Sandbox Code Playgroud)

和AWS CLI:

$ aws s3 rm s3://my-versioned-bucket/ --recursive
Run Code Online (Sandbox Code Playgroud)

但是这两个命令都只是DELETE向S3 添加标记.删除存储桶的命令也不起作用(来自AWS CLI):

$ aws s3 rb s3://my-versioned-bucket/ --force
Cleaning up. Please wait...
Completed 1 part(s) with ... file(s) remaining
remove_bucket failed: s3://my-versioned-bucket/ A client error (BucketNotEmpty) occurred when calling the DeleteBucket operation: The bucket you tried to delete is not empty. You must delete all versions in the bucket.
Run Code Online (Sandbox Code Playgroud)

好吧怎么办?他们的文档中没有关于此的信息.S3Cmd说它是一个"全功能"的S3命令行工具,但它没有引用除自己以外的版本.有没有办法在不使用网络界面的情况下做到这一点,这将永远需要我保持我的笔记本电脑?

Abe*_*ker 39

我遇到了AWS CLI的相同限制.我发现最简单的解决方案是使用Python和boto3:

#!/usr/bin/env python

BUCKET = 'your-bucket-here'

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket(BUCKET)
bucket.object_versions.delete()

# if you want to delete the now-empty bucket as well, uncomment this line:
#bucket.delete()
Run Code Online (Sandbox Code Playgroud)

这个答案的先前版本使用了boto但是该解决方案存在大量密钥的性能问题,正如Chuckles指出的那样.

  • 最佳解决方案!! (3认同)
  • 这对我也很有用!只有障碍在 Arch linux 上成功安装了 boto,这对它来说是一种享受:`pip3 install boto3 --user <username>` (2认同)
  • 这里需要注意的是,“object_versions”似乎不是迭代器,因此它必须在内存中累积整个列表。我看到这个 4 行 python 脚本在实际开始删除任何内容之前消耗了 7GB 虚拟内存。虽然工藤是为了这个职位,但它确实有效。我只是抱怨 boto 的方法不是迭代器这一事实,而人们显然可以在这里受益。 (2认同)

Ale*_*yak 27

看起来到目前为止,EmptyAWS S3 控制台中有一个按钮。 空按钮

只需选择您的存储桶并单击它即可。它会要求您输入“Note”来确认您的决定permanently delete ,这不会删除存储桶本身。


muh*_*hqu 19

如果您必须删除/清空大型 S3 存储桶,则删除每个对象和版本会变得非常低效(而且成本高昂)。让 AWS 使所有对象和版本过期通常更方便。

aws s3api put-bucket-lifecycle-configuration \
  --lifecycle-configuration '{"Rules":[{
      "ID":"empty-bucket",
      "Status":"Enabled",
      "Prefix":"",
      "Expiration":{"Days":1},
      "NoncurrentVersionExpiration":{"NoncurrentDays":1}
    }]}' \
  --bucket YOUR-BUCKET
Run Code Online (Sandbox Code Playgroud)

然后您只需等待 1 天,即可通过以下方式删除存储桶:

aws s3api delete-bucket --bucket YOUR-BUCKET
Run Code Online (Sandbox Code Playgroud)

  • 这是一个聪明的主意:D (3认同)

Dun*_*dan 18

使用boto3它比使用建议的boto解决方案更容易删除S3存储桶中的所有对象版本:

#!/usr/bin/env python
import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('your-bucket-name')
bucket.object_versions.all().delete()
Run Code Online (Sandbox Code Playgroud)

对于非常大量的对象版本也可以正常工作,尽管在这种情况下可能需要一些时间.

  • 如果我想保留当前版本但删除其他所有内容怎么办? (5认同)

Che*_*ers 11

您可以删除版本化s3存储桶中的所有对象.但我不知道如何删除特定对象.

$ aws s3api delete-objects \
      --bucket <value> \
      --delete "$(aws s3api list-object-versions \
      --bucket <value> | \
      jq '{Objects: [.Versions[] | {Key:.Key, VersionId : .VersionId}], Quiet: false}')"
Run Code Online (Sandbox Code Playgroud)

或者没有jq:

$ aws s3api delete-objects \
    --bucket ${bucket_name} \
    --delete "$(aws s3api list-object-versions \
    --bucket "${bucket_name}" \
    --output=json \
    --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"
Run Code Online (Sandbox Code Playgroud)

  • 正确,DeleteMarkers 也需要删除。(刚刚尝试过这个) (2认同)

Ale*_*mon 11

这两行 bash 足以让我启用存储桶删除!

1:删除对象 aws s3api delete-objects --bucket ${buckettoempty} --delete "$(aws s3api list-object-versions --bucket ${buckettoempty} --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"

2:删除标记 aws s3api delete-objects --bucket ${buckettoempty} --delete "$(aws s3api list-object-versions --bucket ${buckettoempty} --query='{Objects: DeleteMarkers[].{Key:Key,VersionId:VersionId}}')"

  • 在命令行上执行此操作可能会产生“参数列表太长”异常。如果遇到这种情况,请利用“list-object-versions”调用中的“--max-items”参数(我批量处理了 500 个)。 (6认同)
  • 或者您可以使用“DeleteMarkers[0:999]” (5认同)

小智 9

我为 N 个桶找到并实现了简单的 bash 循环:

for b in $(ListOfBuckets); do \
    echo "Emptying $b"; \
    aws s3api delete-objects --bucket $b --delete "$(aws s3api list-object-versions --bucket $b --output=json --query='{Objects: *[].{Key:Key,VersionId:VersionId}}')"; \
done
Run Code Online (Sandbox Code Playgroud)


got*_*tit 8

对于那些使用多个配置文件的人 ~/.aws/config

import boto3

PROFILE = "my_profile"
BUCKET = "my_bucket"

session = boto3.Session(profile_name = PROFILE)
s3 = session.resource('s3')
bucket = s3.Bucket(BUCKET)
bucket.object_versions.delete()
Run Code Online (Sandbox Code Playgroud)


Vol*_*soy 7

尽管从技术上讲它不是 AWS CLI,但我建议使用 AWS Tools for Powershell 来完成此任务。然后您可以使用如下简单命令:

Remove-S3Bucket -BucketName {bucket-name} -DeleteBucketContent -Force -Region {region}
Run Code Online (Sandbox Code Playgroud)

如文档中所述,DeleteBucketContent 标志执行以下操作:

“如果设置,则在删除存储桶本身之前,存储桶中的所有剩余对象和/或对象版本都会被删除”

参考:https ://docs.aws.amazon.com/powershell/latest/reference/items/Remove-S3Bucket.html


Nit*_*tin 6

这是一个衬里,您可以将其剪切并粘贴到命令行中以删除所有版本并删除标记(它需要aws工具,用存储桶名称替换yourbucket-name-backup)

echo '#!/bin/bash' > deleteBucketScript.sh \
&& aws --output text s3api list-object-versions --bucket $BUCKET_TO_PERGE \
| grep -E "^VERSIONS" |\
awk '{print "aws s3api delete-object --bucket $BUCKET_TO_PERGE --key "$4" --version-id "$8";"}' >> \
deleteBucketScript.sh && . deleteBucketScript.sh; rm -f deleteBucketScript.sh; echo '#!/bin/bash' > \
deleteBucketScript.sh && aws --output text s3api list-object-versions --bucket $BUCKET_TO_PERGE \
| grep -E "^DELETEMARKERS" | grep -v "null" \
| awk '{print "aws s3api delete-object --bucket $BUCKET_TO_PERGE --key "$3" --version-id "$5";"}' >> \
deleteBucketScript.sh && . deleteBucketScript.sh; rm -f deleteBucketScript.sh;
Run Code Online (Sandbox Code Playgroud)

那么您可以使用:

aws s3 rb s3://bucket-name --force

  • 支持答案的正确性,但这段代码确实很难阅读和理解。 (2认同)

小智 6

如果您想要纯 CLI 方法(使用 jq):

aws s3api list-object-versions \
          --bucket $bucket \
          --region $region \
          --query "Versions[].Key"  \
          --output json | jq 'unique' | jq -r '.[]' | while read key; do
   echo "deleting versions of $key"
   aws s3api list-object-versions \
          --bucket $bucket \
          --region $region \
          --prefix $key \
          --query "Versions[].VersionId"  \
          --output json | jq 'unique' | jq -r '.[]' | while read version; do
     echo "deleting $version"
     aws s3api delete-object \
          --bucket $bucket \
          --key $key \
          --version-id $version \
          --region $region
   done
done          
Run Code Online (Sandbox Code Playgroud)


fae*_*anj 5

一种实现方法是遍历版本并删除它们。在CLI上有些棘手,但是就像您提到的Java一样,这会更简单:

AmazonS3Client s3 = new AmazonS3Client();
String bucketName = "deleteversions-"+UUID.randomUUID();

//Creates Bucket
s3.createBucket(bucketName);

//Enable Versioning
BucketVersioningConfiguration configuration = new BucketVersioningConfiguration(ENABLED);
s3.setBucketVersioningConfiguration(new SetBucketVersioningConfigurationRequest(bucketName, configuration ));

//Puts versions
s3.putObject(bucketName, "some-key",new ByteArrayInputStream("some-bytes".getBytes()), null);
s3.putObject(bucketName, "some-key",new ByteArrayInputStream("other-bytes".getBytes()), null);

//Removes all versions
for ( S3VersionSummary version : S3Versions.inBucket(s3, bucketName) ) {
    String key = version.getKey();
    String versionId = version.getVersionId();          
    s3.deleteVersion(bucketName, key, versionId);
}

//Removes the bucket
s3.deleteBucket(bucketName);
System.out.println("Done!");
Run Code Online (Sandbox Code Playgroud)

如果需要,您还可以批量删除呼叫以提高效率。


Tig*_*eng 5

  1. 要删除指定的对象,请使用jq过滤器。
  2. 您可能需要清理“ DeleteMarkers”,而不仅仅是“ Versions”。
  3. 使用$()代替``,您可以为存储桶名称和键值嵌入变量。
aws s3api delete-objects --bucket bucket-name --delete "$(aws s3api list-object-versions --bucket bucket-name | jq -M '{Objects: [.["Versions","DeleteMarkers"][]|select(.Key == "key-value")| {Key:.Key, VersionId : .VersionId}], Quiet: false}')"
Run Code Online (Sandbox Code Playgroud)


小智 5

我遇到了安倍晋三解决方案的问题,因为list_buckets生成器用于创建一个名为的庞大列表,all_keys而我花了一个小时才完成。这种调整对我来说似乎更好,因为我的存储桶中有近一百万个对象,而且还在不断增加!

import boto

s3 = boto.connect_s3()
bucket = s3.get_bucket("your-bucket-name-here")

chunk_counter = 0 #this is simply a nice to have
keys = []
for key in bucket.list_versions():
    keys.append(key)
    if len(keys) > 1000:
        bucket.delete_keys(keys)
        chunk_counter += 1
        keys = []
        print("Another 1000 done.... {n} chunks so far".format(n=chunk_counter))

#bucket.delete() #as per usual uncomment if you're sure!
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助遇到S3噩梦的其他任何人!

  • 感谢您提供的示例帮助了我,有一件事是在 for 循环之后缺少最后一个 bucket.delete_keys(keys) 来根据您的批处理逻辑捕获任何落后者。 (2认同)