创建AWS Lambda监控S3存储桶目录并通知上传后留存超1小时的对象
问题分析与代码修正
我来帮你梳理下当前代码的核心问题,再一步步给出能实现需求的完整方案:
首先,你的原代码存在几个关键错误,导致无法实现“监控S3目录、发送超时对象通知”的目标:
obj_age函数实现完全错误:s3.ObjectSummary('last_modified')的用法不符合AWS SDK规范,ObjectSummary需要传入桶名和对象键才能获取元数据,last_modified是对象的属性而非参数。- 逻辑判断逻辑混乱:
len(obj_age)是试图获取函数对象的长度,这会直接抛出错误;而且时间比较的逻辑颠倒了,应该是当前时间 - 对象最后修改时间 > 1小时才符合“留存超1小时”的条件。 - 缺少遍历指定目录对象的逻辑:原代码没有批量检查S3目标目录下的所有对象,无法覆盖需求场景。
- 缺少实际的通知发送逻辑:代码里完全没实现“发送通知”的核心动作(比如通过SNS/SES)。
正确实现方案
要实现这个需求,我们不能只依赖S3事件触发(它只能在对象上传时触发一次,无法后续定时检查时长),而是需要用EventBridge定时触发Lambda,让Lambda定期扫描指定目录,校验对象留存时长并发送通知。
步骤1:配置EventBridge定时触发
创建一个EventBridge规则,设置定时触发频率(比如每15分钟一次,表达式:cron(*/15 * * * ? *)),将目标设置为你的Lambda函数。这样Lambda就能定期执行扫描任务。
步骤2:Lambda代码实现
以下是完整的可运行代码,包含对象遍历、时长校验和SNS通知功能:
import boto3 from datetime import datetime, timedelta, timezone def lambda_handler(event, context): # 初始化AWS客户端 s3_client = boto3.client('s3') sns_client = boto3.client('sns') # 自定义配置参数 BUCKET_NAME = 'mybucketname' TARGET_PREFIX = 'your-target-directory/' # 指定监控的目录,注意末尾要加斜杠 OLDER_THAN_HOURS = 1 SNS_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:your-sns-topic' # 替换成你的SNS主题ARN # 获取当前UTC时间(S3对象的last_modified是UTC时区,避免时区误差) now_utc = datetime.now(timezone.utc) threshold_time = now_utc - timedelta(hours=OLDER_THAN_HOURS) # 遍历指定前缀下的所有对象(处理分页,避免对象超过1000个时漏扫) paginator = s3_client.get_paginator('list_objects_v2') page_iterator = paginator.paginate(Bucket=BUCKET_NAME, Prefix=TARGET_PREFIX) old_objects = [] for page in page_iterator: if 'Contents' not in page: continue for obj in page['Contents']: # 获取对象的最后修改时间(UTC时区) last_modified = obj['LastModified'] # 判断对象是否留存超过指定时长 if last_modified < threshold_time: old_objects.append(f"对象键: {obj['Key']}, 最后修改时间: {last_modified.strftime('%Y-%m-%d %H:%M:%S UTC')}") # 如果存在超时对象,发送SNS通知 if old_objects: message = f"在S3桶 {BUCKET_NAME} 的目录 {TARGET_PREFIX} 中,发现 {len(old_objects)} 个留存超过 {OLDER_THAN_HOURS} 小时的对象:\n" message += "\n".join(old_objects) # 发送通知到SNS主题 sns_client.publish( TopicArn=SNS_TOPIC_ARN, Subject='S3对象留存超时提醒', Message=message ) return { 'statusCode': 200, 'body': f"已发送通知,共发现 {len(old_objects)} 个超时对象" } else: return { 'statusCode': 200, 'body': f"未发现留存超过 {OLDER_THAN_HOURS} 小时的对象" }
步骤3:配置Lambda IAM权限
确保Lambda的执行角色拥有以下权限:
s3:ListBucket:用于遍历S3桶中的对象sns:Publish:用于发送SNS通知
关键细节说明
- 时区处理:S3对象的
LastModified属性是UTC时间,所以我们用datetime.now(timezone.utc)获取当前UTC时间,避免时区差异导致的判断错误。 - 分页处理:如果目标目录下的对象超过1000个,
list_objects_v2会返回分页结果,用分页器paginator可以确保遍历所有对象。 - 目录匹配:通过
Prefix参数指定监控目录时,末尾必须加斜杠(比如data/),否则会匹配所有以data开头的对象(包括data123.txt这类非目录内的对象)。
内容的提问来源于stack exchange,提问作者Aadhinarayanan J
相关产品推荐
相关产品推荐

