0

I am using this script on Ubuntu & it works fine

status="$(curl -Is http://www.google.com | head -1)"
validate=( $status )
if [ ${validate[-2]} == "200" ]; then
   echo "OK"
else
   echo "NOT RESPONDING"
fi

but when I run it on my Raspberry Pi it generates this error:

validate: bad array index
[: ==: unary operator expected

I guess it's from the bash version I tried:

if [ "$ {validate [-2]"} == "200" ]; then

But it does not work.

myUbuntu bash version : 5.0.17
myRaspebbry PI bash version : 5.0.3
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Emma Lang
  • 1
  • 3
  • 1
    You don't need to quote the `200`. You _do_ need to quote the `${validate[-2]}` (and even then, that's code that's very picky about which versions of bash it works with; I don't recommend it). – Charles Duffy Oct 23 '20 at 20:15
  • Note also that `array=( $value )` is an antipattern. See [BashPitfalls #50](http://mywiki.wooledge.org/BashPitfalls#hosts.3D.28_.24.28aws_....29_.29). – Charles Duffy Oct 23 '20 at 20:15
  • Works fine with 5.0.0 und 5.0.16. – Cyrus Oct 23 '20 at 20:15
  • 1
    have you verified the array contains what you think it does? for debugging purposes ... after `validate=( $status )` add `typeset -p validate` (to display the contents of the array); if the array is empty, or the position referenced by `[-2]` does not exist, you will get the `unary operator expected` error ... which would seem to support the idea the array does not contain what you think it does ... which in turn could be an issue with the `curl` command not executing properly from the raspberry ... – markp-fuso Oct 23 '20 at 20:16
  • ...also, the current value of `IFS` in your script will change how things get split during assignment into the array. – Charles Duffy Oct 23 '20 at 20:19
  • the error occurs when array is empty : `${validate[-2]}` -2 is not valid, and then because the double quotes are missing and single square bracket == becomes the first argument of test – Nahuel Fouilleul Oct 23 '20 at 20:30
  • `-2 is not valid` -2 is valid - it's the second element from the back – KamilCuk Oct 23 '20 at 21:01
  • I often use `read foo status bar < <(curl -Is http://www.google.com)` for this: `head` is useless: `read` will read 1st line, then *leave* subprocess. Then `$status` could hold a number or nothing. – F. Hauri - Give Up GitHub Oct 24 '20 at 22:09
  • I you're just interested by 1st line of server answer, you could try to create your own HTTP request and play with `/dev/tcp/ip.ad.re.ss/port` instead of curl. See [how I play with tcp ports](https://stackoverflow.com/a/64412835/1765658) – F. Hauri - Give Up GitHub Oct 24 '20 at 22:16

2 Answers2

1

While this answer does not solve your Bash issue, there is no need to use any shell features* to get the HTTP status code. curl can extract it for you:

status=$(curl -o /dev/null -w '%{http_code}' http://www.google.com)

The -o /dev/null option tells it to drop the retrieved page ("save" it to /dev/null).

The -w option tells it to print some pieces of the response after it prints the response. %{http_code} is exactly what you need.

To read more about curl options type curl --help in your terminal or read its documentation on the web.


* Except for capturing the output in a variable.

axiac
  • 68,258
  • 9
  • 99
  • 134
  • Thank you for your help but for what I do your answer does not suit I invite you to read my previous comment in response to Sergio Rodriguez you will understand – Emma Lang Oct 24 '20 at 04:52
0

Try this - works on that bash version 5.0.3 a double braket [[...]] is needed:

status="$(curl -Is http://www.google.com | head -1)"
validate=( $status )
if [[ ${validate[-2]} == "200" ]]; then
echo "OK"
else
echo "NOT RESPONDING"
fi

explanation: "unary operator expected" error in Bash if condition

try this option, but run it as $bash file.sh:

IFS=' '
while sleep 1;
    do ip=$(printf "%d.%d.%d.%d\n" "$((RANDOM % 256))" "$((RANDOM % 256))" "$((RANDOM % 256))" "$((RANDOM % 256))")
        
        # display current IP
        echo $ip
        # get url status
        status="$(curl -Is http://ip | head -1)"
        
        # read line 
        read -a strarr <<<  "$status"

        # if: empty print error  
        # else: check for second value in arr and execute http command 
        if [[ -z "$status" ]]
            then
                echo "invalid entry or NOT RESPONDING: {$status}"
            else
                if [[ ${strarr[1]} == "200" ]]
                    then
                        echo "OK" info="$(http -h http://$ip)" 
                        echo -e "http://$ip \n\n$info " >> iplist.txt
                 fi        
        fi
done
Sergio Rodriguez
  • 8,258
  • 3
  • 18
  • 25
  • it's good but halfway because in real I do not put the google url the code is in a loop which generates IP randomly & for each IP it tests to see if there is a site behind & so I have this error: validate: bad array index The error only occurs with the Raspberry Pi (Debian) not on desktop PC with Ubuntu – Emma Lang Oct 24 '20 at 04:45
  • Can you provide a full working copy of the code with the loop? – Sergio Rodriguez Oct 24 '20 at 06:32
  • Oh no, I work for the N.S.A ! Just kidding I know bash a little bit but not like a pro. it works this https://httpie.org/ Here is the code: while sleep 1; do ip=$(printf "%d.%d.%d.%d\n" "$((RANDOM % 256))" "$((RANDOM % 256))" "$((RANDOM % 256))" "$((RANDOM % 256))") echo $ip status="$(curl -Is http://$ip | head -1)" validate=( $status ) if [ ${validate[-2]} == "200" ]; then echo "OK" info="$(http -h http://$ip)" echo -e "http://$ip \n\n$info " >> iplist.txt else echo "NOT RESPONDING" fi done – Emma Lang Oct 24 '20 at 09:00
  • I made a few changes, but you need to run as '$bash file.sh' explicitly. There are a few issues with bash 5.0.3 – Sergio Rodriguez Oct 24 '20 at 12:55