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]} Nov 17, 2020 at 19:21
  • 1
    What’s does the output of your aws ... | jq ... command look like?
    – bxm
    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" 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)
    – roaima
    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
    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. 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. 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 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/… 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 .