19

我曾经尝试都s3cmd如何使用CLI在AWS S3中删除版本化存储桶?

$ s3cmd -r -f -v del s3://my-versioned-bucket/ 

而且AWS CLI:

$ aws s3 rm s3://my-versioned-bucket/ --recursive 

但是这两个命令只需添加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. 

好的......怎么样? their documentation没有这方面的信息。 S3Cmd表示这是一个“全功能”的S3命令行工具,但它使得no reference to versions不是它自己的。有没有办法做到这一点,而不使用Web界面,这将永远需要,并要求我保持我的笔记本电脑?

+0

据我所知,您需要遍历对象版本并将它们批量删除1000 ... –

+0

如果有某处有示例Java代码,那就太好了。 AWS文档真的很糟糕...... – NobleUplift

回答

3

一种方法是遍历版本并删除它们。了一下就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!"); 

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

+1

我实际上会尝试让一个多线程程序运行来删除我的S3存储桶中的每个“文件夹”(其中有四个文件夹),并且如果需要的话,将线程拆分为较大的文件夹到'first/1',...,'first/9'等......但是一个同事,我最终删除了所有使用Web界面和Cyber​​duck的版本。感谢您的帮助,但我需要它! – NobleUplift

6

您可以删除版本化s3存储桶中的所有对象。 但我不知道如何删除指定的对象。 aws s3api delete-objects --bucket <value> --delete "$(aws s3api list-object-versions --bucket <value> | jq '{Objects: [.Versions[] | {Key:.Key, VersionId : .VersionId}], Quiet: false}')"

希望它对你有帮助。

+0

这个工程,但我不得不将对象更改为对象和安静。这显然是区分大小写的。 –

+1

这可惜不适用于1000多个对象.. –

+0

任何方式来解决1000+对象限制? –

19

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

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() 

这个答案的先前版本使用boto但解决方案必须具有大量键性能问题轻笑指出。

+0

绝对有效! –

4
  1. 用于使用jq过滤器删除指定对象。
  2. 您可能需要清理'DeleteMarkers'而不仅仅是'版本'。
  3. 使用$()而不是``,可以为bucket-name和key-value嵌入变量。
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}')" 
+0

此oneliner(以及上面的http://stackoverflow.com/a/31086407/465684)外观和工作很好,但它们不适合有超过1000个对象要删除的情况(严格限制s3api删除对象调用)。 –

+0

@ tiger-peng在调用DeleteObjects操作时出现错误“发生错误(MalformedXML):您提供的XML格式不正确或未针对我们发布的模式进行验证”。任何想法发生了什么? –

1

这里是一个班轮你可以剪切并粘贴到命令行删除所有版本和删除标记(它需要AWS工具,它与斗名称替换yourbucket名备份)

echo '#!/bin/bash' > deleteBucketScript.sh && aws --output text s3api list-object-versions --bucket yourbucket-name-backup | grep -E "^VERSIONS" | awk '{print "aws s3api delete-object --bucket yourbucket-name-backup --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 yourbucket-name-backup | grep -E "^DELETEMARKERS" | grep -v "null" | awk '{print "aws s3api delete-object --bucket yourbucket-name-backup --key "$3" --version-id "$5";"}' >> deleteBucketScript.sh && . deleteBucketScript.sh; rm -f deleteBucketScript.sh; 

那么你可以使用:

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

+0

我的同事设置了生命周期规则,将在接下来的几天内慢慢删除版本控制桶。你的回答很具有讽刺意味,因为它永远会在我们的系统中完成S3版本的终结。 – NobleUplift

5

我遇到了Abe's solution问题,因为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! 

希望这有助于任何人遇到这个S3噩梦!

+0

谢谢你这个帮助我的例子,有一件事是在for循环之后缺少一个最终的bucket.delete_keys(keys),以便根据你的批处理逻辑来捕获任何零碎的东西。 – Sean

12

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

#!/usr/bin/env python 
import boto3 

s3 = boto3.resource('s3') 
bucket = s3.Bucket('your-bucket-name') 
bucket.object_versions.all().delete() 

正常工作也非常大量的对象版本,虽然它可能需要一些时间那种情况。

相关问题