在AWS SSM中检索命令调用结果时遇InvocationDoesNotExist错误
解决SSM get_command_invocation返回InvocationDoesNotExist的问题
这种情况我碰到过好几次,明明send_command成功拿到了命令ID,但立刻查结果就报这个错,多半是几个常见的小问题导致的,咱们一步步排查:
1. 先给SSM Agent留够初始化时间
SSM命令从AWS服务端传到EC2实例的Agent需要一点时间,刚调用完send_command就立刻调用get_command_invocation,Agent可能还没接收到命令,自然查不到。建议先等个5-10秒再开始轮询,轮询间隔设为2-3秒就好,别太频繁刷接口。
2. 确认get_command_invocation的参数完全正确
这是最容易踩坑的点!三个参数一个都不能错:
CommandId:必须是send_command返回的那个完整ID,别手滑输错或者复制漏了字符InstanceId:要和发送命令时指定的实例ID完全一致,别搞混了其他实例PluginName:这个90%的人会忘! 对于Ubuntu的Shell命令,插件名是aws:runShellScript,如果不传这个参数,SSM不知道你要查哪个插件的执行结果,直接就报不存在。正确的调用应该是这样:
response = ssm_client.get_command_invocation( CommandId='your-command-id-here', InstanceId='i-xxxxxxxxx', PluginName='aws:runShellScript' )
3. 检查EC2实例上的SSM Agent状态
虽然你说Agent在运行,但还是要确认它真的正常工作。登录实例执行:
sudo systemctl status amazon-ssm-agent
看输出是不是active (running)。如果不是,重启Agent试试:
sudo systemctl restart amazon-ssm-agent
另外,查看Agent日志,看看有没有接收到目标命令的记录:
sudo tail -f /var/log/amazon/ssm/amazon-ssm-agent.log
如果日志里完全没看到你那个CommandId,说明命令根本没传到实例,得往下排查网络和权限。
4. 验证实例的SSM注册状态
去AWS控制台的Systems Manager -> 节点管理 -> 托管实例里,看看你的EC2实例是不是处于「在线」状态。如果是离线,那命令肯定传不过去:
- 先确认实例的IAM角色有没有附加
AmazonSSMManagedInstanceCore政策(你说已经配置,但再核对一遍总没错) - 如果实例在私有子网,要确保它能访问SSM服务:要么配置VPC端点(SSM的端点是
com.amazonaws.region.ssm),要么通过NAT网关访问公网,SSM Agent需要和AWS服务端通信才能接收命令。
5. 确认命令的目标实例范围
如果你发送命令时用了Targets参数(比如按标签选择实例),要确保你查询的InstanceId确实在目标实例列表里。比如标签写错了,导致命令发到了其他实例,你查这个实例自然找不到。
最后给你一个完整的轮询示例代码,把上面的要点都包含进去了:
import boto3 import time # 初始化SSM客户端 ssm_client = boto3.client('ssm', region_name='your-region') # 发送Shell命令 send_cmd_response = ssm_client.send_command( InstanceIds=['i-xxxxxxxxx'], DocumentName='AWS-RunShellScript', Parameters={'commands': ['echo "Hello from SSM"', 'uptime']} ) command_id = send_cmd_response['Command']['CommandId'] print(f"已发送命令,ID: {command_id}") # 等待命令初始化 time.sleep(5) # 轮询命令结果 max_retries = 20 retry_count = 0 success = False while retry_count < max_retries: try: invocation_result = ssm_client.get_command_invocation( CommandId=command_id, InstanceId='i-xxxxxxxxx', PluginName='aws:runShellScript' ) status = invocation_result['Status'] print(f"当前命令状态: {status}") if status in ['Success', 'Failed', 'TimedOut']: print(f"命令执行结果:") print(f"标准输出:\n{invocation_result['StandardOutputContent']}") if status == 'Failed': print(f"错误输出:\n{invocation_result['StandardErrorContent']}") success = True break else: # 未完成,继续等待 time.sleep(3) retry_count += 1 except ssm_client.exceptions.InvocationDoesNotExist: print("命令尚未在实例上初始化,继续等待...") time.sleep(3) retry_count += 1 if not success: print(f"轮询{max_retries}次后仍未获取结果,超时退出")
内容的提问来源于stack exchange,提问作者Remilekun Basaru
相关产品推荐
相关产品推荐

