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

时间:2015-04-22 21:22:15

标签: amazon-web-services amazon-s3 command-line-interface aws-cli s3cmd

我已经尝试了s3cmd

$ 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不是它自己的。有没有办法在不使用网络界面的情况下做到这一点,这将永远需要我保持我的笔记本电脑?

21 个答案:

答案 0 :(得分:35)

我遇到了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()

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

答案 1 :(得分:15)

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

#!/usr/bin/env python
import boto3

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

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

答案 2 :(得分:9)

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

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

或者没有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}}')"

答案 3 :(得分:7)

这两条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}}')"

答案 4 :(得分:4)

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

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

答案 5 :(得分:4)

我遇到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噩梦!

答案 6 :(得分: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!");

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

答案 7 :(得分:3)

如果要使用纯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          

答案 8 :(得分:3)

如果必须删除/清空大型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

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

aws s3api delete-bucket --bucket YOUR-BUCKET

答案 9 :(得分:2)

您可以使用生命周期规则从AWS控制台执行此操作。

打开有问题的桶。单击顶部的“管理”选项卡。 确保选择了“生命周期子选项卡”。 点击+添加生命周期规则

在第1步(名称和范围)上,输入规则名称(例如removeall) 单击第二步(转换)的下一步 保持原样,然后单击下一步。

您现在处于3. Expiration步骤。 选中当前版本和以前版本的复选框。 单击“使对象的当前版本过期”复选框,然后为“自对象创建后_____天后输入数字1” 单击“永久删除以前的版本”复选框,然后为1输入数字1。 “从成为旧版本_____天后”

点击“清理不完整的分段上传”复选框 并在“自上传开始____天后”输入数字1 点击下一步 回顾一下您刚才所做的事情。
点击保存

回到一天,看看效果如何。

enter image description here

答案 10 :(得分:2)

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

Remove-S3Bucket -BucketName {bucket-name} -DeleteBucketContent -Force -Region {region}

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

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

参考:https://docs.aws.amazon.com/powershell/latest/reference/

答案 11 :(得分:1)

截止目前,AWS S3控制台中有一个Empty按钮。 Empty Button

只需选择您的存储桶,然后单击它即可。它将要求您通过键入permanently delete来确认您的决定。 请注意,这不会删除存储桶本身。

答案 12 :(得分:1)

对于通过let rec bar (ls : string list) : string list= match ls with | [] -> [] | x :: xs -> (if (foo x) then "true" else "false") :: bar xs 使用多个配置文件的用户

~/.aws/config

答案 13 :(得分:0)

我为 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

答案 14 :(得分:0)

您可以使用 aws-cli 删除 s3 存储桶

<块引用>

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

如果您的计算机中未安装 aws cli,您可以使用以下命令: 对于 Linux 或 ubuntu:

<块引用>

sudo apt-get install aws-cli

然后检查它是否安装:

<块引用>

aws --version

现在通过提供 aws-access-credentials 进行配置

<块引用>

aws 配置

然后给出访问密钥和秘密访问密钥以及您所在的地区

答案 15 :(得分:0)

要添加到此处提供的python解决方案:如果遇到boto.exception.S3ResponseError: S3ResponseError: 400 Bad Request错误,请尝试使用以下数据创建〜/ .boto文件:

[Credentials]
aws_access_key_id = aws_access_key_id
aws_secret_access_key = aws_secret_access_key
[s3]
host=s3.eu-central-1.amazonaws.com
aws_access_key_id = aws_access_key_id
aws_secret_access_key = aws_secret_access_key

帮助我删除了法兰克福地区的存储桶。

原始答案:https://stackoverflow.com/a/41200567/2586441

答案 16 :(得分:0)

这对我有用。也许正在运行某些新版本,并且超过1000个项目。现在已经运行了几百万个文件。但是,它经过半天仍未完成,并且无法在AWS GUI = /

中进行验证
# Set bucket name to clearout
BUCKET = 'bucket-to-clear'

import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket(BUCKET)

max_len         = 1000      # max 1000 items at one req
chunk_counter   = 0         # just to keep track
keys            = []        # collect to delete

# clear files
def clearout():
    global bucket
    global chunk_counter
    global keys
    result = bucket.delete_objects(Delete=dict(Objects=keys))

    if result["ResponseMetadata"]["HTTPStatusCode"] != 200:
        print("Issue with response")
        print(result)

    chunk_counter += 1
    keys = []
    print(". {n} chunks so far".format(n=chunk_counter))
    return

# start
for key in bucket.object_versions.all():
    item = {'Key': key.object_key, 'VersionId': key.id}
    keys.append(item)
    if len(keys) >= max_len:
        clearout()

# make sure last files are cleared as well
if len(keys) > 0:
    clearout()

print("")
print("Done, {n} items deleted".format(n=chunk_counter*max_len))
#bucket.delete() #as per usual uncomment if you're sure!

答案 17 :(得分:0)

此bash脚本位于:https://gist.github.com/weavenet/f40b09847ac17dd99d16

为我工作。

我将脚本另存为:delete_all_versions.sh,然后简​​单地运行:

./ delete_all_versions.sh my_foobar_bucket

而且没有任何缺陷。

不需要python或boto或其他任何东西。

答案 18 :(得分:0)

https://gist.github.com/wknapik/191619bfa650b8572115cd07197f3baf

#!/usr/bin/env bash

set -eEo pipefail
shopt -s inherit_errexit >/dev/null 2>&1 || true

if [[ ! "$#" -eq 2 || "$1" != --bucket ]]; then
    echo -e "USAGE: $(basename "$0") --bucket <bucket>"
    exit 2
fi

# $@ := bucket_name
empty_bucket() {
    local -r bucket="${1:?}"
    for object_type in Versions DeleteMarkers; do
        local opt=() next_token=""
        while [[ "$next_token" != null ]]; do
            page="$(aws s3api list-object-versions --bucket "$bucket" --output json --max-items 1000 "${opt[@]}" \
                        --query="[{Objects: ${object_type}[].{Key:Key, VersionId:VersionId}}, NextToken]")"
            objects="$(jq -r '.[0]' <<<"$page")"
            next_token="$(jq -r '.[1]' <<<"$page")"
            case "$(jq -r .Objects <<<"$objects")" in
                '[]'|null) break;;
                *) opt=(--starting-token "$next_token")
                   aws s3api delete-objects --bucket "$bucket" --delete "$objects";;
            esac
        done
    done
}

empty_bucket "${2#s3://}"

例如empty_bucket.sh --bucket foo

这将删除所有对象版本并删除存储桶中1000个批次中的标记。此后,可以使用aws s3 rb s3://foo删除存储桶。

需要bash,awscli和jq。

答案 19 :(得分:0)

到目前为止,我发现最简单的方法是使用此CLI工具s3wipe。它作为docker容器提供,因此您可以像这样使用它:

$ docker run -it --rm slmingol/s3wipe --help
usage: s3wipe [-h] --path PATH [--id ID] [--key KEY] [--dryrun] [--quiet]
              [--batchsize BATCHSIZE] [--maxqueue MAXQUEUE]
              [--maxthreads MAXTHREADS] [--delbucket] [--region REGION]

Recursively delete all keys in an S3 path

optional arguments:
  -h, --help               show this help message and exit
  --path PATH              S3 path to delete (e.g. s3://bucket/path)
  --id ID                  Your AWS access key ID
  --key KEY                Your AWS secret access key
  --dryrun                 Don't delete. Print what we would have deleted
  --quiet                  Suprress all non-error output
  --batchsize BATCHSIZE    # of keys to batch delete (default 100)
  --maxqueue MAXQUEUE      Max size of deletion queue (default 10k)
  --maxthreads MAXTHREADS  Max number of threads (default 100)
  --delbucket              If S3 path is a bucket path, delete the bucket also
  --region REGION          Region of target S3 bucket. Default vaue `us-
                           east-1`

示例

这是一个示例,其中我删除存储桶中的所有版本控制对象,然后删除存储桶:

$ docker run -it --rm slmingol/s3wipe \
   --id $(aws configure get default.aws_access_key_id) \
   --key $(aws configure get default.aws_secret_access_key) \
   --path s3://bw-tf-backends-aws-example-logs \
   --delbucket
[2019-02-20@03:39:16] INFO: Deleting from bucket: bw-tf-backends-aws-example-logs, path: None
[2019-02-20@03:39:16] INFO: Getting subdirs to feed to list threads
[2019-02-20@03:39:18] INFO: Done deleting keys
[2019-02-20@03:39:18] INFO: Bucket is empty.  Attempting to remove bucket

工作原理

这里有一些需要解压的东西,但是上面的操作如下:

  • docker run -it --rm mikelorant/s3wipe-交互式运行s3wipe容器,并在每次执行后将其删除
  • --id--key-传入我们的访问密钥和访问ID
  • aws configure get default.aws_access_key_id-检索我们的密钥ID
  • aws configure get default.aws_secret_access_key-检索我们的关键秘密
  • --path s3://bw-tf-backends-aws-example-logs-我们要删除的存储桶
  • --delbucket-清空后删除存储桶

参考文献

答案 20 :(得分:-1)

我发现其他答案要么不完整,要么需要安装外部依赖项(如boto),因此这里的答案是受这些启发的但更深一些。

Working with Delete Markers中所述,必须先完全删除其版本,然后才能删除版本桶,该过程分为两个步骤:

  1. “删除”存储桶中的所有版本对象,将其标记为 已删除,但实际上并没有删除它们
  2. 通过删除所有删除标记对象来完成删除

这是对我有用的纯CLI解决方案(受到其他答案的启发):

#!/usr/bin/env bash

bucket_name=...

del_s3_bucket_obj()
{
    local bucket_name=$1
    local obj_type=$2
    local query="{Objects: $obj_type[].{Key:Key,VersionId:VersionId}}"
    local s3_objects=$(aws s3api list-object-versions --bucket ${bucket_name} --output=json --query="$query")
    if ! (echo $s3_objects | grep -q '"Objects": null'); then
        aws s3api delete-objects --bucket "${bucket_name}" --delete "$s3_objects"
    fi
}

del_s3_bucket_obj ${bucket_name} 'Versions'
del_s3_bucket_obj ${bucket_name} 'DeleteMarkers'

完成此操作后,以下各项将起作用:

aws s3 rb "s3://${bucket_name}"

但是,如果有人可以报告那太棒了,则不知道它将如何处理1000多个对象。