1

I'm running a command from a bash 4 prompt to gather the output from AWS CLI commands that pull the output of an AWS SSM run document. I can have it output in multiple formats including text or json (default). I am, unsuccessfully so far, attempting put this output into an array so I can loop through the output until every value in the array equals 2 or higher.

#!/bin/bash

aws ec2 reboot-instances --instance-ids `aws ec2 describe-instances --filters "Name=tag:RebootGroup,Values=01" --query 'Reservations[].Instances[].InstanceId' --output text`

sleep 30

completeLoop=false

while [ ! ${completeLoop} ]
do
    ssmID=$(aws ssm send-command --document-name "AWS-RunPowerShellScript" --document-version "1" --targets '[{"Key":"tag:RebootGroup","Values":["01"]}]' --parameters '{"commands":["$wmi = Get-WmiObject -Class Win32_OperatingSystem ","$uptimeMinutes = ($wmi.ConvertToDateTime($wmi.LocalDateTime)-$wmi.ConvertToDateTime($wmi.LastBootUpTime) | select-object -expandproperty \"TotalMinutes\")","[int]$uptimeMinutes"],"workingDirectory":[""],"executionTimeout":["3600"]}' --timeout-seconds 600 --max-concurrency "50" --max-errors "0" --region us-west-2 --output text --query "Command.CommandId")

    declare -a a
    readarray -t upTimeArray <<< $(aws ssm list-command-invocations --command-id "$ssmID" --details --output json | jq '.CommandInvocations[].CommandPlugins[].Output')

    if [[ " ${upTimeArray[@]} " -gt 5 ]]; then
        echo "Uptime is greater than 5 minutes."
        completeLoop=true
    else
        completeLoop=false
    fi

done

I've made some progress here but now I am trying to figure out how to remove the carriage return/new line from the output.

Here is my array simplified to just output the value of the items in the array. I assume I need to use sed to strip the '\r\n' from each line but I am having trouble doing so.

declare -a a

readarray -t upTimeArray <<< $(aws ssm list-command-invocations --command-id "$ssmID" --details --output json | jq '.CommandInvocations[].CommandPlugins[].Output')

for i in "${upTimeArray[@]}"
do
  echo $i
done

is returning the following

"1\r\n"
"1\r\n"

I need it to return just "1" for each line so I can iterate over the array until each equals 2 or greater.


EDIT #2

I made progress with help provided here but eventually fully solved my issues with the question and scripting in this second question https://stackoverflow.com/questions/65362975/bash-aws-cli-trying-to-figure-out-how-to-validate-an-array-of-uptimes-with-2-ch

6
  • Note that $my_array is equivalent to ${my_array[0]} Commented Nov 17, 2020 at 19:21
  • 1
    What’s does the output of your aws ... | jq ... command look like?
    – bxm
    Commented Nov 17, 2020 at 22:49
  • @bxm the same...I have tried various options with sed to strip the \r\n without success so far. ws ssm list-command-invocations --command-id "$ssmID" --details --output json | jq '.CommandInvocations[].CommandPlugins[].Output' "1\r\n" "1\r\n" Commented Nov 17, 2020 at 22:52
  • 1
    What bxm means is that we don't know what your aws... command produces, so we can't recommend anything to process its output. (I'd suggest you add it to your question) Commented Nov 17, 2020 at 23:59
  • Are you saying you literally see \r\n as visible characters in the response, or are you talking about their non-visible equivalents?
    – bxm
    Commented Nov 19, 2020 at 12:11

1 Answer 1

0

You never actually enter the loop:

$ completeLoop=false
$ while [ ! $completeLoop ]; do date; done; echo complete
complete

The [ command, when given a single argument (setting aside ! and the trailing ]), will return success if the argument is not empty. Both "true" and "false" are not empty.

To act on the actual boolean result of true and false commands, omit [:

completeLoop=false
count=0
# ....vvvvvvvvvvvvvvv
while ! "$completeLoop"; do
  echo in loop
  (( ++count == 5 )) && completeLoop=true
done
echo complete
in loop
in loop
in loop
in loop
in loop
complete

You want

readarray -t upTimeArray < <(
   aws ssm list-command-invocations --command-id "$ssmID" --details --output json |
     sed $'s/\r$//' |
     jq -r '.CommandInvocations[].CommandPlugins[].Output'
)

Using sed to remove the trailing carriage return (the newline is handled automatically), and jq -r to output the "raw" value without quotes.

I'm redirecting from a process substitution instead of a here-string. Same results.

It's OK to add extra whitespace inside $(...) for readability

4
  • Thank you I will dig into this today and do some thorough testing. I think you helped on my last question as well, really appreciate it. Commented Nov 18, 2020 at 15:57
  • End of year work is killing me but hopefully I will get to dig into this soon and report back as to whether I was able to solve based on your very well laid out explanation/solution. Commented Nov 19, 2020 at 18:27
  • Testing to see if the values in the array are greater than 5 keeps failing on me and I assume it's due to the empty lines in the array? You can see the line breaks below when I print the array: : printf '%s\n' "${upTimeArray[@]}" 494 494 Commented Dec 15, 2020 at 0:59
  • Gave you credit here because your assistance and the assistance in this second question eventually led me to a working solution stackoverflow.com/questions/65362975/… Commented Dec 21, 2020 at 15:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .