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

如何使用boto3查询180天内未活跃S3 Bucket的最后访问时间

查询S3 Bucket最近180天未活跃状态及最后访问时间(Boto3实现)

要实现这个需求,首先要明确:S3本身不会自动记录Bucket级别的最后访问时间,需要借助CloudWatch Metrics或S3访问日志来获取相关数据。以下是两种可行的实现方案:

方案一:通过CloudWatch Metrics判断活跃度并获取最后访问时间

此方案无需额外配置(S3默认会向CloudWatch发送基础访问指标),适合快速批量检查所有Bucket。

代码实现

import boto3
from datetime import datetime, timedelta

# 初始化Boto3客户端
s3_client = boto3.client('s3')
cloudwatch_client = boto3.client('cloudwatch')

# 定义时间范围:最近180天
end_time = datetime.utcnow()
inactive_threshold = timedelta(days=180)
start_time = end_time - inactive_threshold

# 获取所有S3 Bucket
buckets = s3_client.list_buckets()['Buckets']

for bucket in buckets:
    bucket_name = bucket['Name']
    bucket_creation_date = bucket['CreationDate']
    
    # 查询最近180天的总请求数
    metric_response = cloudwatch_client.get_metric_statistics(
        Namespace='AWS/S3',
        MetricName='AllRequests',
        Dimensions=[
            {'Name': 'BucketName', 'Value': bucket_name},
            {'Name': 'StorageType', 'Value': 'AllStorageTypes'}
        ],
        StartTime=start_time,
        EndTime=end_time,
        Period=86400,  # 按天统计
        Statistics=['Sum'],
        Unit='Count'
    )
    
    datapoints = metric_response['Datapoints']
    # 判断最近180天是否有访问活动
    has_recent_activity = any(dp['Sum'] > 0 for dp in datapoints)
    
    if not has_recent_activity:
        # 查找最后一次有活动的时间(若存在)
        last_access_time = bucket_creation_date
        
        # 扩大查询范围至Bucket创建以来的所有数据
        extended_metric_response = cloudwatch_client.get_metric_statistics(
            Namespace='AWS/S3',
            MetricName='AllRequests',
            Dimensions=[
                {'Name': 'BucketName', 'Value': bucket_name},
                {'Name': 'StorageType', 'Value': 'AllStorageTypes'}
            ],
            StartTime=bucket_creation_date,
            EndTime=start_time,
            Period=86400,
            Statistics=['Sum'],
            Unit='Count'
        )
        
        extended_datapoints = extended_metric_response['Datapoints']
        if extended_datapoints:
            # 按时间倒序排序,取最后一次有请求的时间
            sorted_dps = sorted(extended_datapoints, key=lambda x: x['Timestamp'], reverse=True)
            last_access_time = sorted_dps[0]['Timestamp']
        
        print(f"Bucket: {bucket_name}")
        print(f"最近180天状态:未活跃")
        print(f"最后访问/创建时间:{last_access_time.strftime('%Y-%m-%d %H:%M:%S UTC')}\n")

注意事项

  • 权限要求:IAM用户需拥有s3:ListAllMyBuckets和cloudwatch:GetMetricStatistics权限。
  • 指标延迟:CloudWatch指标存在约15分钟的延迟,无法实时获取最新访问记录。
  • 无访问记录的Bucket:若Bucket从未有过任何请求,最后访问时间将显示为Bucket创建时间。

方案二:通过S3访问日志解析最后访问时间

此方案需要提前为目标Bucket配置访问日志(将日志存储到指定的日志Bucket),能提供更精确的访问记录。

代码实现

import boto3
from datetime import datetime, timedelta

# 初始化Boto3客户端
s3_client = boto3.client('s3')

# 配置日志Bucket信息
log_bucket_name = "your-log-bucket-name"  # 存储访问日志的Bucket
log_prefix = "s3-access-logs/"  # 日志文件的前缀路径

# 定义时间范围:最近180天
end_time = datetime.utcnow()
inactive_threshold = timedelta(days=180)
start_time = end_time - inactive_threshold

# 获取所有目标Bucket
target_buckets = s3_client.list_buckets()['Buckets']

for bucket in target_buckets:
    bucket_name = bucket['Name']
    # 构造日志文件的起始筛选前缀(匹配目标Bucket的日志)
    log_start_after = f"{log_prefix}{bucket_name}-{start_time.strftime('%Y-%m-%d')}"
    
    # 列出最近180天内的日志文件
    log_response = s3_client.list_objects_v2(
        Bucket=log_bucket_name,
        Prefix=f"{log_prefix}{bucket_name}-",
        StartAfter=log_start_after
    )
    
    log_files = log_response.get('Contents', [])
    if not log_files:
        print(f"Bucket: {bucket_name}")
        print(f"最近180天状态:未活跃(无访问日志记录)\n")
        continue
    
    # 取最新的日志文件
    latest_log_file = sorted(log_files, key=lambda x: x['LastModified'], reverse=True)[0]
    
    # 下载并解析日志文件
    log_content = s3_client.get_object(
        Bucket=log_bucket_name,
        Key=latest_log_file['Key']
    )['Body'].read().decode('utf-8')
    
    # 解析日志中的最后访问时间(日志格式需与实际配置匹配)
    # 示例日志格式:192.168.1.1 - - [05/Mar/2024:14:30:00 +0000] "GET /bucket/obj.txt HTTP/1.1" 200 ...
    last_access_line = log_content.strip().split('\n')[-1]
    time_str = last_access_line.split('[')[1].split(']')[0]
    last_access_time = datetime.strptime(time_str, '%d/%b/%Y:%H:%M:%S %z')
    
    print(f"Bucket: {bucket_name}")
    print(f"最后访问时间:{last_access_time.strftime('%Y-%m-%d %H:%M:%S %Z')}\n")

注意事项

  • 日志配置:需提前为目标Bucket开启访问日志,指定日志存储的Bucket和前缀。
  • 日志格式:不同的日志配置会导致格式差异,需根据实际日志格式调整解析逻辑。
  • 性能优化:若日志文件过大,建议按时间分片查询,避免一次性下载大文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:23:13