How to create a loop in bash that is waiting for a webserver to respond?

Viewed 115067

How to create a loop in bash that is waiting for a webserver to respond?

It should print a "." every 10 seconds or so, and wait until the server starts to respond.

Update, this code tests if I get a good response from the server.

if curl --output /dev/null --silent --head --fail "$url"; then
  echo "URL exists: $url"
else
  echo "URL does not exist: $url"
fi
9 Answers

I wanted to limit the maximum number of attempts. Based on Thomas's accepted answer I made this:

attempt_counter=0
max_attempts=5

until $(curl --output /dev/null --silent --head --fail http://myhost:myport); do
    if [ ${attempt_counter} -eq ${max_attempts} ];then
      echo "Max attempts reached"
      exit 1
    fi

    printf '.'
    attempt_counter=$(($attempt_counter+1))
    sleep 5
done

The poster asks a specific question about printing ., but I think most people coming here are looking for the solution below, as it is a single command that supports finite retries.

curl --head -X GET --retry 5 --retry-connrefused --retry-delay 1 http://myhost:myport

You can also combine timeout and tcp commands like this. It will timeout after 60s instead of waiting indefinitely

timeout 60 bash -c 'until echo > /dev/tcp/myhost/myport; do sleep 5; done'

The following snippet:

  • Wait's until all URLs from the arguments return 200
  • Expires after 30 second if one URL is not available
  • One curl requests timeouts after 3 seconds

Just put it into a file and use it like a generic script to wait until the required services are available.

#/bin/bash

##############################################################################################
# Wait for URLs until return HTTP 200
#
# - Just pass as many urls as required to the script - the script will wait for each, one by one
#
# Example: ./wait_for_urls.sh "${MY_VARIABLE}" "http://192.168.56.101:8080"
##############################################################################################

wait-for-url() {
    echo "Testing $1"
    timeout --foreground -s TERM 30s bash -c \
        'while [[ "$(curl -s -o /dev/null -m 3 -L -w ''%{http_code}'' ${0})" != "200" ]];\
        do echo "Waiting for ${0}" && sleep 2;\
        done' ${1}
    echo "${1} - OK!"
}

echo "Wait for URLs: $@"

for var in "$@"; do
    wait-for-url "$var"
done

Gist: https://gist.github.com/eisenreich/195ab1f05715ec86e300f75d007d711c

Related