7

I've got the following AWS CLI commands to run the PowerShell's Invoke-WebRequest command:

instanceId=i-0xyz # Change this.
cmdId=$(aws ssm send-command --instance-ids "$instanceId" --document-name "AWS-RunPowerShellScript" --query "Command.CommandId" --output text --parameters commands='"While ($i -le 10) {Invoke-WebRequest -UseBasicParsing -Uri http://example.com; $i += 1}"')
sleep 1
aws ssm list-command-invocations --command-id "$cmdId" --details --query "CommandInvocations[*].CommandPlugins[*].Output[]" --output text

However, the output is truncated:

...
StatusCode        : 200
StatusDescription : OK
Content           : <!doctype html>
                    <html>
                    <head>
                        <title>Example Domain</title>

                        <meta charset="utf-8" />
                        <meta http-equiv="Content-type" content="text/html; 
                    charset=utf-8" />
                        <meta name="viewport" conten...
------------------Output truncated-------------------

How I can run aws ssm list-command-invocations command, so the output won't be truncated?

3 Answers 3

6

According to this ssm tutorial, SSM send-command output is truncated at 2500 characters. To work around that, you must send your output to an S3 bucket using the --output-s3-bucket-name parameter.

5

Here is a helper Bash script which uses aws ssm send-command with --output-s3-bucket-name parameter to run the command and the result is stored in the S3 bucket, then displayed to the standard output.

#/usr/bin/env bash -xe
# Script to run PowerShell script on the Windows instance, then uploads the output to S3 bucket.
instanceId="$1"
bucketName="$2"
bucketDir="Output"
[ $# -le 2 ] && { echo "Usage: $0 instance_id bucket_name command"; exit 1; }
aws s3 ls ${bucketName} > /dev/null
cmdId=$(aws ssm send-command --instance-ids "$instanceId" --document-name "AWS-RunPowerShellScript" --query "Command.CommandId" --output text  --output-s3-bucket-name "$bucketName" --output-s3-key-prefix "$bucketDir" --parameters commands="'${@:3}'")
while [ "$(aws ssm list-command-invocations --command-id "$cmdId" --query "CommandInvocations[].Status" --output text)" == "InProgress" ]; do sleep 1; done
outputPath=$(aws ssm list-command-invocations --command-id "$cmdId" --details --query "CommandInvocations[].CommandPlugins[].OutputS3KeyPrefix" --output text)
aws s3 ls s3://${bucketName}/${outputPath}/stderr.txt && aws s3 cp --quiet s3://${bucketName}/${outputPath}/stderr.txt /dev/stderr
aws s3 cp --quiet s3://${bucketName}/${outputPath}/stdout.txt /dev/stdout

Example:

./run_ec2_ps_cmd_s3.sh i-0xyz my-bucket-name 'While ($i -le 10) {(Invoke-WebRequest -UseBasicParsing -Uri http://example.com).Content; $i++}'
6
  • 1
    Few remarks: 1. Why the first s3 ls ? this sounds an api query for nothing. 2. Testing InProgress is brittle, ssm commands can be in Pending state and your script will fail. 3. The availability of the files on S3 can be delayed for a few seconds, doing a retry loop is usually usefull to get the content back
    – Tensibai
    Commented Feb 21, 2018 at 15:06
  • @Tensibai 1. To make sure the bucket exists, otherwise no point in executing the command. 2. So far I've noticed only InProgress, will check if I got Pendingas well, 3. If SSM command has been completed, I think we can assume the files are already there. Didn't have problems so far, althought still testing this script heavily.
    – kenorb
    Commented Feb 21, 2018 at 15:09
  • That's just what I have observed for my part with run shell script for linux instances :)
    – Tensibai
    Commented Feb 21, 2018 at 15:12
  • According to this list-command-invocations link, the possible values for Status are InProgress, Success, TimedOut, Cancelled, Failed, so no pending as far as I could find.
    – kenorb
    Commented Feb 21, 2018 at 15:15
  • Aww, indeed, I'm using list-commands as I target multiples instances, this command has a "Pending" status also.
    – Tensibai
    Commented Feb 21, 2018 at 15:23
1

If someone is still running into this issue another option is to gzip the output at source and decompress after pulling it back.

Following is an example in Python running command in Linux EC2 instance -

command = 'set -o pipefail; cat my_large_file.txt | gzip | base64 -w0'
ssm_client.send_command(
    InstanceIds=[ec2_instance_id],
    DocumentName="AWS-RunShellScript",
    Parameters={'commands': [command]}, )

cmd_out = self._ssm_client.get_command_invocation(
    CommandId=command_id,
    InstanceId=ec2_instance_id,
)

# Decompress gzipped output 
result =  zlib.decompress(base64.b64decode(cmd_out['StandardOutputContent']), 16 + zlib.MAX_WBITS).decode('utf-8')

The limit is 24k chars as mentioned here in AWS Boto documentation.

1
  • 1
    this sounds like a good suggestion that might get the job done, can you add an example of doing it to make it a better looking answer?
    – Peter Turner
    Commented May 24 at 15:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.