5
\$\begingroup\$

I am working on a project in which I need to make a URL call to one of my servers from a bash shell script.

 http://hostname.domain.com:8080/beat

After hitting the above URL, I will be getting the below response, from which I need to parse and extract the value of state:

num_retries_allowed: 3 count: 30 count_behind: 100 state: INIT num_rounds: 60 hour_col: 2 day_col: 0

Now I will keep on hitting the above URL every 10 seconds until the value of the state variable is equal to INIT:

state = INIT

If the state is equal to INIT then I will exit successfully out of the shell script, otherwise I will keep on trying until the state becomes INIT.

Also, if the state: string is missing in the $DATA variable by any chance, then I want to assign 0 to the state variable. So if state is equal to 0, then I will also exit out of the shell script successfully.

I am hitting the above URL and checking whether I got a successful response or not. If I got a successful response, then I am breaking out (which means server is running fine), but if I didn't got successful response, then I am checking whether my server is running or not on port 8080. If it is not running, then I will start the server. And I am retrying this for a period of 15 times, and after 15 tries if the server hasn't come back up, then exit out of the shell script with a non-zero status code.

Is the below shell script correct?

#!/bin/bash

HOSTNAME=$hostname
DATA=""
RETRY=15

echo $HOSTNAME

sleep 1m

while true; do

    while [ $RETRY -gt 0 ]
    do
        DATA=$(wget -O - -q -t 1 http://$HOSTNAME:8080/beat)
        if [ $? -eq 0 ]
        then
            break
        else
            if lsof -Pi :8080 -sTCP:LISTEN -t >/dev/null ;
            then
                echo "Server is running"
            else
                echo "Server is not running so re-starting the server here"
                # starting server here
            fi
            let RETRY-=1
            sleep 30
        fi
    done

    if [ $RETRY -eq 0 ]
    then
        echo "Server is still down. Exiting out now." >&2
        exit 2
    fi

    echo "Server is up. Now parsing the data out of the beat."

    #grep $DATA for state
    state=$(grep -oP 'state: \K\S+' <<< "$DATA")
    [[ -z "$state" ]] && state=0

    echo $state

    #verify the condiitons
    if [[ $state -eq "INIT" || $state -eq "0" ]]; then exit 0; fi

    #wait another 10 seconds
    sleep 10

done

Is there any better way of doing this if I am doing anything wrong?

\$\endgroup\$
  • \$\begingroup\$ Is $hostname set in your environment, or is that just an example? \$\endgroup\$ – ferada Feb 3 '15 at 22:17
  • \$\begingroup\$ Yes its being set externally. I have tested that and it works fine. \$\endgroup\$ – david Feb 3 '15 at 22:22
1
\$\begingroup\$

Instead of grepping for state, I would use bash regex support:

    re='state: ([A-Z]*)'
    state=0
    [[ "$DATA" =~ $re ]] && state=${BASH_REMATCH[1]}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I know this is an old post, but why would you use Bash Regex instead of Grep? \$\endgroup\$ – Malachi Jul 9 '18 at 17:33
  • 1
    \$\begingroup\$ @Malachi the Bash regex check is performed within the same Bash process. grep would be an extra process \$\endgroup\$ – janos Jul 9 '18 at 17:46
2
\$\begingroup\$

Inconsistent logic

In one place the script checks http://$HOSTNAME:8080/beat, in another, it checks for a local process listening on port 8080. This only makes sense if $HOSTNAME the name of the local machine. It will make more sense to replace $HOSTNAME with hard-coded localhost.

Use exit code directly

Instead of this:

DATA=$(wget -O - -q -t 1 http://$HOSTNAME:8080/beat)
if [ $? -eq 0 ]
then
    break

You could use the exit code directly like this:

if DATA=$(wget -O - -q -t 1 http://$HOSTNAME:8080/beat)
then
    break

Another way:

DATA=$(wget -O - -q -t 1 http://$HOSTNAME:8080/beat) && break

Math in Bash

Instead of this:

let RETRY-=1

There are slightly simpler alternatives:

((RETRY -= 1))
((RETRY--))
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Is $hostname set in your environment ...

Yes its being set externally.

Maybe consider using a command line argument, that's a bit more obvious.

The inner while loop could be replaced with a for loop for counting. And curl defaults to stdout, so you could use that instead of wget.

Now, since you're using lsof the server is running on your machine, right? In that case you should probably have the PID of the server process somewhere or you can also use ps/pgrep to check whether it is running (before restarting it I mean).

Rest looks good I think.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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