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?
3 Answers 3
Instead of grepping for state
, I would use bash regex support:
re='state: ([A-Z]*)'
state=0
[[ "$DATA" =~ $re ]] && state=${BASH_REMATCH[1]}
-
\$\begingroup\$ I know this is an old post, but why would you use Bash Regex instead of Grep? \$\endgroup\$Malachi– Malachi2018年07月09日 17:33:32 +00:00Commented Jul 9, 2018 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– janos2018年07月09日 17:46:43 +00:00Commented Jul 9, 2018 at 17:46
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--))
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.
$hostname
set in your environment, or is that just an example? \$\endgroup\$