Alexandre Krabbe
Alexandre Krabbe

Reputation: 771

AWS Java SDK - Running a command using SSM on EC2 instances

I could not find any examples of this online, nor could I find the documentation explaining how to do this. Basically I have a list of Windows EC2 instances and I need to run the quser command in each one of them to check how many users are logged on.

It is possible to do this using the AWS Systems Manager service and running the AWS-RunPowerShellScript command. I only found examples using the AWS CLI, something like this:

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

But how can I accomplish this using the AWS Java SDK 1.11.x ?

Upvotes: 6

Views: 2546

Answers (2)

Yang_2333
Yang_2333

Reputation: 714

In SDK 1.11.x , use sth like:

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

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

Upvotes: 0

Mugdha
Mugdha

Reputation: 181

@Alexandre Krabbe it's more than a year before you asked this question. So not sure the answer will help you. But I was trying to do the same recently and that led me to this unanswered question. I ended up solving the problem and thought my answer could help other people facing the same problem. Here is a code snippet for the same:

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
    }
}

Upvotes: 8

Related Questions