backend/e2e/bin/wait-for-hosts.sh (view raw)
1#!/bin/sh
2
3#
4# Waits for the given host(s) to be available before executing a given command.
5# Tests for availability by using netcat to connect to the hosts via TCP.
6#
7# Usage:
8# ./wait-for-hosts.sh [-q] [-t seconds] [host:port] [...] [-- command args...]
9#
10# The script accepts multiple `host:port` combinations as arguments or defined
11# as WAIT_FOR_HOSTS environment variable, separating the `host:port`
12# combinations via spaces.
13#
14# The status output can be made quiet by adding the `-q` argument or by setting
15# the environment variable WAIT_FOR_HOSTS_QUIET to `1`.
16#
17# The default timeout of 10 seconds can be changed via `-t seconds` argument or
18# by setting the WAIT_FOR_HOSTS_TIMEOUT environment variable to the desired
19# number of seconds.
20#
21# The command defined after the `--` argument separator will be executed if all
22# the given hosts are reachable.
23#
24# Copyright 2016, Sebastian Tschan
25# https://blueimp.net
26#
27# Licensed under the MIT license:
28# https://opensource.org/licenses/MIT
29#
30
31set -e
32
33is_integer() {
34 test "$1" -eq "$1" 2> /dev/null
35}
36
37set_timeout() {
38 if ! is_integer "$1"; then
39 printf 'Error: "%s" is not a valid timeout value.\n' "$1" >&2
40 return 1
41 fi
42 TIMEOUT="$1"
43}
44
45connect_to_service() {
46 nc -w 1 -z "$1" "$2"
47}
48
49quiet_echo() {
50 if [ "$QUIET" -ne 1 ]; then echo "$@" >&2; fi
51}
52
53wait_for_host() {
54 HOST="${1%:*}"
55 PORT="${1#*:}"
56 if ! is_integer "$PORT"; then
57 printf 'Error: "%s" is not a valid host:port combination.\n' "$1" >&2
58 return 1
59 fi
60 if [ "$QUIET" -ne 1 ]; then
61 printf "Waiting for host: %-${PADDING}s ... " "$1" >&2
62 fi
63 TIME_LIMIT=$(($(date +%s)+TIMEOUT))
64 while ! OUTPUT="$(connect_to_service "$HOST" "$PORT" 2>&1)"; do
65 if [ "$(date +%s)" -ge "$TIME_LIMIT" ]; then
66 quiet_echo timeout
67 if [ -n "$OUTPUT" ]; then
68 quiet_echo "$OUTPUT"
69 fi
70 return 1
71 fi
72 sleep 1
73 done
74 quiet_echo ok
75}
76
77set_padding() {
78 PADDING=0
79 while [ $# != 0 ]; do
80 case "$1" in
81 -t) shift 2;;
82 -q) break;;
83 --) break;;
84 *) test ${#1} -gt $PADDING && PADDING=${#1}; shift;;
85 esac
86 done
87}
88
89QUIET=${WAIT_FOR_HOSTS_QUIET:-0}
90set_timeout "${WAIT_FOR_HOSTS_TIMEOUT:-10}"
91
92if [ "$QUIET" -ne 1 ]; then
93 # shellcheck disable=SC2086
94 set_padding $WAIT_FOR_HOSTS "$@"
95fi
96
97while [ $# != 0 ]; do
98 case "$1" in
99 -t) set_timeout "$2"; shift 2;;
100 -q) QUIET=1; shift;;
101 --) shift; break;;
102 *) wait_for_host "$1"; shift;;
103 esac
104done
105
106for HOST in $WAIT_FOR_HOSTS; do
107 wait_for_host "$HOST"
108done
109
110exec "$@"