EC2实例运行超8小时触发SNS通知时输出异常如何解决
问题原因
你的代码无法得到预期结果是由多个语法错误和逻辑错误共同导致的,具体问题如下:
- 语法缩进错误:Python对缩进敏感,你写的
if str(timeDiff)>='08:00:00':判断语句下方的SNS发布逻辑没有正确缩进,代码根本无法正常执行。 - 时间比较逻辑完全错误:你把时间差对象
timedelta转成字符串后用字符串规则比较大小,属于核心逻辑硬伤。字符串比较是逐字符匹配ASCII值,比如运行7小时的时间差字符串是7:00:00,首字符'7'的ASCII码比08:00:00的首字符'0'大,哪怕运行时长只有7小时也会被误判为满足8小时条件;而运行时长超过1天的时间差字符串为1 day, 0:00:00,虽然比较结果碰巧符合要求,但逻辑完全不可靠。 - 时区不一致风险:EC2接口返回的
launch_time是UTC时区时间,你通过strftime/strptime做格式转换时直接丢失了时区信息,如果Lambda运行环境的时区被修改,时间差计算结果会完全错误。 - 遍历逻辑错误:你在遍历实例的循环内部,只要碰到第一个符合条件的实例就直接return终止函数,后续的实例完全不会被检查;且你从循环一开始就累加所有实例的信息到通知内容里,会把运行时长不足8小时的实例也带入告警消息。
- 资源配置不一致:你在函数外已经指定
ap-south-1区域初始化EC2资源,函数内部又重新初始化了不带区域参数的EC2资源,会默认读取Lambda环境的默认区域配置,可能导致查不到目标区域的实例。
修正后代码
import boto3 from datetime import datetime, timedelta, timezone # 固定配置项 REGION = 'ap-south-1' SNS_TOPIC_ARN = 'arn:aws:sns:ap-south-1:1234566789:test-sns' # 8小时阈值,直接用timedelta类型做比较,避免字符串逻辑错误 THRESHOLD = timedelta(hours=8) def lambda_handler(event, context): # 初始化客户端时统一指定区域 ec2 = boto3.resource('ec2', region_name=REGION) sns = boto3.client('sns', region_name=REGION) # 筛选带active标签的*运行中*实例,排除已停止/终止的实例 instances = ec2.instances.filter( Filters=[ {'Name': 'tag:Session', 'Values': ['active']}, {'Name': 'instance-state-name', 'Values': ['running']} ] ) alert_content = [] # 统一取UTC当前时间,和EC2返回的启动时间时区完全一致 current_time = datetime.now(timezone.utc) for instance in instances: run_duration = current_time - instance.launch_time # 直接比较timedelta对象,逻辑100%可靠 if run_duration >= THRESHOLD: alert_content.append( f"实例ID: {instance.id}\n" f"启动时间(UTC): {instance.launch_time.strftime('%Y-%m-%d %H:%M:%S')}\n" f"检查时间(UTC): {current_time.strftime('%Y-%m-%d %H:%M:%S')}\n" f"已运行时长: {run_duration}\n" "----------------------------------------" ) # 仅当存在超时长实例时才发送SNS通知 if alert_content: message = "以下EC2实例运行时长已超过8小时,请及时处理:\n\n" + "\n".join(alert_content) resp = sns.publish( TopicArn=SNS_TOPIC_ARN, Message=message, Subject='EC2运行时长超限告警' ) return resp return {"status": "no instances over runtime threshold"}
配置注意事项
- 给Lambda绑定的执行角色必须添加两个权限:允许
ec2:DescribeInstances操作查询实例信息,允许sns:Publish操作发送SNS通知,否则运行时会抛出权限不足的错误。 - 如果需要按本地时区计算运行时长,必须给所有时间对象统一加上对应时区信息,禁止混用带时区和不带时区的时间对象,否则会抛出异常或者计算结果错误。
内容的提问来源于stack exchange,提问作者Praveen Sivakumar
相关产品推荐
相关产品推荐

