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

如何通过Lambda借助SSM逐行执行EC2命令并实时获取输出?

Lambda 在 Linux EC2 上逐行执行命令并实时获取输出的方案

现有实现的问题

当前通过SSM批量发送命令的代码如下:

import boto3, time

client = boto3.client("ssm", region_name="eu-west-1")
INSTANCE_ID = "some-instance-id"

commands = ["ls -la","uname"]
response = client.send_command(
    InstanceIds=[INSTANCE_ID],
    DocumentName="AWS-RunShellScript",
    Parameters={"commands": commands},
)
command_id = response["Command"]["CommandId"]
while True:
    time.sleep(3)
    result = client.get_command_invocation(
        CommandId=command_id,
        InstanceId=INSTANCE_ID,
    )
    if result["Status"] == "InProgress":
        continue
    print(result["StandardOutputContent"])
    print(result["StandardErrorContent"])
    break

存在两个明显弊端:

  • 批量发送命令时,一旦某条命令失败,无法直接定位具体是哪条命令出错
  • 固定3秒的time.sleep轮询会浪费不必要的等待时间,降低执行效率

需求是实现类似以下的逻辑:逐个发送命令,立即获取每条命令的输出,出错时直接终止流程:

commands = ["ls -la", "uname"]
for command in commands:
    output, errors = some_client.send_command(command)
    if errors:
        break

尝试过SSM.Client.start_session方法,但Lambda运行环境没有预装Session Manager插件,无法使用交互式会话。

可行解决方案

方法1:拆分命令为单独的SendCommand调用

每次仅发送一条命令,单独追踪执行状态和结果,同时优化轮询间隔提升效率。代码示例:

import boto3
import time
from botocore.exceptions import ClientError

ssm_client = boto3.client("ssm", region_name="eu-west-1")
INSTANCE_ID = "some-instance-id"

def run_single_command(command):
    try:
        # 发送单条命令
        cmd_response = ssm_client.send_command(
            InstanceIds=[INSTANCE_ID],
            DocumentName="AWS-RunShellScript",
            Parameters={"commands": [command]}
        )
        cmd_id = cmd_response["Command"]["CommandId"]
        
        # 轮询命令状态,用1秒间隔替代3秒,减少等待
        while True:
            invocation_result = ssm_client.get_command_invocation(
                CommandId=cmd_id,
                InstanceId=INSTANCE_ID
            )
            # 命令完成(成功/失败/取消)时返回结果
            if invocation_result["Status"] not in ["Pending", "InProgress"]:
                return (invocation_result["StandardOutputContent"], 
                        invocation_result["StandardErrorContent"])
            time.sleep(1)
    except ClientError as e:
        return "", str(e)

# 逐个执行命令,出错即终止
commands = ["ls -la", "uname"]
for cmd in commands:
    output, errors = run_single_command(cmd)
    print(f"=== 命令 `{cmd}` 输出 ===")
    print(output)
    if errors:
        print(f"=== 命令 `{cmd}` 错误 ===")
        print(errors)
        break

这个方案的优势:

  • 每条命令的结果独立,能精准定位出错的命令
  • 缩短轮询间隔,提升整体执行效率
  • 不需要额外插件,Lambda原生支持SSM的SendCommand和get_command_invocation接口

方法2:自定义SSM文档实现分步执行(可选)

如果需要更结构化的步骤管理,可以创建自定义SSM文档,将每个命令作为单独执行步骤,这样能在结果中查看每个步骤的状态。示例文档(JSON格式):

{
  "schemaVersion": "2.2",
  "description": "逐行执行Shell命令",
  "parameters": {
    "command1": {
      "type": "String",
      "description": "第一条命令"
    },
    "command2": {
      "type": "String",
      "description": "第二条命令"
    }
  },
  "mainSteps": [
    {
      "action": "aws:runShellScript",
      "name": "executeCmd1",
      "inputs": {
        "runCommand": ["{{ command1 }}"]
      }
    },
    {
      "action": "aws:runShellScript",
      "name": "executeCmd2",
      "inputs": {
        "runCommand": ["{{ command2 }}"]
      }
    }
  ]
}

在Lambda中调用该文档时,可通过get_command_invocation的StepExecutions字段获取每个步骤的具体结果。不过这种方式需要预先定义步骤数量,灵活性不如方法1。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:36:00