You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并发删除多S3桶内容的Python及Bash脚本报错求助

问题解决指南

一、Python脚本 KeyError: 'endpoint_resolver' 错误修复

这个错误是由于boto3客户端实例线程不安全引发的随机问题,加上旧版本依赖的潜在bug导致。

解决方案

  1. 升级依赖包
    先确保boto3和botocore是最新版本:

    pip install --upgrade boto3 botocore
    
  2. 修改脚本:每个并发任务单独创建S3客户端
    不要在多线程间共享boto3客户端实例,每个线程内单独初始化客户端。以下是优化后的脚本,支持超1000对象批量删除、并发处理6个桶:

    import boto3
    from concurrent.futures import ThreadPoolExecutor, as_completed
    
    def empty_bucket(bucket_name):
        # 每个任务单独创建S3客户端
        s3 = boto3.client('s3')
        paginator = s3.get_paginator('list_objects_v2')
        delete_batch = []
    
        # 分页遍历所有对象
        for page in paginator.paginate(Bucket=bucket_name):
            if 'Contents' in page:
                delete_batch.extend([{'Key': obj['Key']} for obj in page['Contents']])
            
            # 批量删除(每次最多1000个对象)
            while len(delete_batch) >= 1000:
                batch = delete_batch[:1000]
                s3.delete_objects(Bucket=bucket_name, Delete={'Objects': batch})
                delete_batch = delete_batch[1000:]
        
        # 删除剩余不足1000的对象
        if delete_batch:
            s3.delete_objects(Bucket=bucket_name, Delete={'Objects': delete_batch})
    
    if __name__ == '__main__':
        target_buckets = ["bucket1", "bucket2", "bucket3", "bucket4", "bucket5", "bucket6"]
        # 并发数设为6,和桶数量一致
        with ThreadPoolExecutor(max_workers=6) as executor:
            futures = [executor.submit(empty_bucket, bucket) for bucket in target_buckets]
            # 等待所有任务完成并捕获异常
            for future in as_completed(futures):
                try:
                    future.result()
                    print(f"桶内容清空完成")
                except Exception as e:
                    print(f"清空桶失败: {str(e)}")
    

二、Bash脚本 jq 错误修复

Cannot index array with string "Key" 错误是因为当桶内无对象时,aws s3api list-objects-v2 返回结果中没有Contents字段,jq直接索引会报错。同时单对象删除速度慢,改用批量删除优化。

解决方案

修改脚本逻辑,先判断Contents是否存在,同时用批量删除提升效率:

#!/bin/bash
BUCKETS=("bucket1" "bucket2" "bucket3" "bucket4" "bucket5" "bucket6")

empty_bucket() {
    local BUCKET=$1
    # 分页获取所有对象Key,处理空桶场景
    aws s3api list-objects-v2 --bucket "$BUCKET" --output json | jq -c '
        if .Contents then .Contents[] | {Key: .Key} else empty end
    ' > "/tmp/${BUCKET}_keys.tmp"

    # 按1000个一组批量删除
    jq -s -c '.[] | _nwise(1000)' "/tmp/${BUCKET}_keys.tmp" | while read -r BATCH; do
        aws s3api delete-objects --bucket "$BUCKET" --delete "{\"Objects\": $BATCH}"
    done

    # 若桶开启版本化,需额外删除版本和删除标记(可选)
    aws s3api list-object-versions --bucket "$BUCKET" --output json | jq -c '
        (.Versions[]? | {Key: .Key, VersionId: .VersionId}),
        (.DeleteMarkers[]? | {Key: .Key, VersionId: .VersionId})
    ' > "/tmp/${BUCKET}_versions.tmp"

    jq -s -c '.[] | _nwise(1000)' "/tmp/${BUCKET}_versions.tmp" | while read -r BATCH; do
        aws s3api delete-objects --bucket "$BUCKET" --delete "{\"Objects\": $BATCH}"
    done

    rm "/tmp/${BUCKET}_keys.tmp" "/tmp/${BUCKET}_versions.tmp"
}

# 并发执行所有桶的清空任务
for BUCKET in "${BUCKETS[@]}"; do
    empty_bucket "$BUCKET" &
done
wait

三、aws s3 rm 提速方案

如果坚持用官方CLI,可添加--parallel参数开启并发删除:

aws s3 rm s3://your-bucket --recursive --parallel

但批量删除的效率仍远高于此命令。

内容的提问来源于stack exchange,提问作者gamechanger17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:50:38