AWS Java SDK - 在 EC2 实例上使用 SSM 运行命令

Posted

技术标签:

【中文标题】AWS Java SDK - 在 EC2 实例上使用 SSM 运行命令【英文标题】:AWS Java SDK - Running a command using SSM on EC2 instances 【发布时间】:2020-02-25 20:54:42 【问题描述】:

我在网上找不到任何此类示例,也找不到解释如何执行此操作的文档。基本上我有一个 Windows EC2 实例列表,我需要在每个实例中运行quser 命令来检查有多少用户登录。

可以使用 AWS Systems Manager 服务并运行 AWS-RunPowerShellScript 命令来执行此操作。我只找到了使用 AWS CLI 的示例,如下所示:

aws ssm send-command --instance-ids "instance ID" --document-name "AWS-RunPowerShellScript" --comment "Get Users" --parameters commands=quser --output text

但我如何使用 AWS Java SDK 1.11.x 完成此任务?

【问题讨论】:

如果在 SDKV2 中,您可以使用Waiter 逻辑。 【参考方案1】:

@Alexandre Krabbe 你问这个问题已经一年多了。所以不确定答案会对你有帮助。但我最近也在尝试做同样的事情,这让我想到了这个悬而未决的问题。我最终解决了这个问题,并认为我的回答可以帮助其他面临同样问题的人。这是相同的代码sn-p:

public void runCommand() throws InterruptedException 
    //Command to be run
    String ssmCommand = "ls -l";
    Map<String, List<String>> params = new HashMap<String, List<String>>()
        put("commands", new ArrayList<String>() add(ssmCommand); );
    ;
    int timeoutInSecs = 5;
    //You can add multiple command ids separated by commas
    Target target = new Target().withKey("InstanceIds").withValues("instance-id");
    //Create ssm client.
    //The builder could be chosen as per your preferred way of authentication
    //use withRegion for specifying your region
    AWSSimpleSystemsManagement ssm = AWSSimpleSystemsManagementClientBuilder.standard().build();
    //Build a send command request
    SendCommandRequest commandRequest = new SendCommandRequest()
            .withTargets(target)
            .withDocumentName("AWS-RunShellScript")
            .withParameters(params);
    //The result has commandId which is used to track the execution further
    SendCommandResult commandResult = ssm.sendCommand(commandRequest);
    String commandId = commandResult.getCommand().getCommandId();
    //Loop until the invocation ends
    String status;
    do 
        ListCommandInvocationsRequest request = new ListCommandInvocationsRequest()
                .withCommandId(commandId)
                .withDetails(true);
        //You get one invocation per ec2 instance that you added to target
        //For just a single instance use get(0) else loop over the instanced
        CommandInvocation invocation = ssm.listCommandInvocations(request).getCommandInvocations().get(0);
        status = invocation.getStatus();
        if(status.equals("Success")) 
            //command output holds the output of running the command
            //eg. list of directories in case of ls
            String commandOutput = invocation.getCommandPlugins().get(0).getOutput();
            //Process the output
        
        //Wait for a few seconds before you check the invocation status again
        try 
            TimeUnit.SECONDS.sleep(timeoutInSecs);
         catch (InterruptedException e) 
            //Handle not being able to sleep
        
     while(status.equals("Pending") || status.equals("InProgress"));
    if(!status.equals("Success")) 
        //Command ended up in a failure
    

【讨论】:

String commandOutput = invocation.getCommandPlugins().get(0).getOutput();似乎只返回错误窗口输出。无论如何要获得实际输出?【参考方案2】:

在 SDK 1.11.x 中,使用类似:

val waiter = ssmClient.waiters().commandExecuted()

waiter.run(WaiterParameters(GetCommandInvocationRequest()
    .withCommandId(commandId)
    .withInstanceId(instanceId)
))

【讨论】:

以上是关于AWS Java SDK - 在 EC2 实例上使用 SSM 运行命令的主要内容,如果未能解决你的问题,请参考以下文章

带有 PHP SDK 的 AWS EC2 - 等到实例具有公共 DNS 名称

AWS SDK/CLI 访问错误,AWS Redshift create-cluster 的 EC2 实例凭证

使用 aws-sdk ruby​​ gem 知道自己的实例 ID

使用boto3 Python SDK返回AWS EC2可用性区域属性

如何在使用Java AWS开发工具包创建AWS EC2时提供实例名称

如何在 Java 中以编程方式启动和停止 Amazon EC2 实例