Skip to content

Commit 7a14483

Browse files
committed
Initial commit
0 parents  commit 7a14483

File tree

4 files changed

+317
-0
lines changed

4 files changed

+317
-0
lines changed

.editorconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# top-most EditorConfig file
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 4
7+
end_of_line = lf
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true
11+
12+
[*.{md,sh,ps1}]
13+
max_line_length = 0
14+
trim_trailing_whitespace = false

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
**/.dev

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## wait-host
2+
3+
`wait-host.sh` is an sh script that will wait on the availability of a host and TCP port.
4+
Specially designed to be used in Alpine container, It is useful for synchronizing interdependent services, such as linked docker containers.
5+
You can use it to wait for a database to be ready, for php-fpm connection, ...
6+
7+
8+
### Usage
9+
10+
```
11+
Usage: wait-host.sh [host:port] [OPTIONS] [-- command args]
12+
13+
-h | --host Host or IP under test
14+
-p | --port TCP port under test
15+
Alternatively, you can specify the host and port as host:port
16+
-d | --delay Delay in seconds, before trying to contact the host.
17+
-m | --message Delay message
18+
-s | --strict Only execute subcommand if the test succeeds
19+
-q | --quiet Don't output any status messages
20+
-t | --timeout Timeout in seconds, zero for no timeout
21+
22+
-- command args Execute command with args after the test finishes
23+
24+
Examples:
25+
wait-host.sh mysql:3306 Wait indefinitely for port 3306 to be available on host mysql
26+
wait-host.sh google.com:80 Wait indefinitely for port 80 to be available on host google.com
27+
wait-host.sh mysql:3306 -t 15 Wait a maximum of 15s for port 3306 to be available on host mysql
28+
29+
Full example:
30+
wait-host.sh mysql:3306 \
31+
-t 120 \
32+
-d 2 \
33+
-m 'Waiting for database connection on host: and port:' \
34+
-s \
35+
-- echo "Database connection established" \
36+
|| echo "Error while trying to connect to the database"
37+
38+
Wait 120 seconds for port 3306 to be available on host mysql
39+
Display a custom message every 2 seconds
40+
Display a custom message on success
41+
Display a custom message on error (strict mode)
42+
```

wait-host.sh

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
#!/bin/sh
2+
3+
#
4+
# `wait-host.sh` is an sh script that will wait on the availability of a host and TCP port.
5+
# Specially designed to be used in Alpine container, It is useful for synchronizing
6+
# interdependent services, such as linked docker containers.
7+
#
8+
# You can use it to wait for a database to be ready, for php-fpm connection, ...
9+
#
10+
11+
12+
# set -e : Exit the script if any statement returns a non-true return value.
13+
# set -u : Exit the script when using uninitialised variable.
14+
#set -eu
15+
16+
# Default values
17+
readonly progname=$(basename $0)
18+
19+
# Display help message
20+
function getHelp() {
21+
cat << USAGE >&2
22+
23+
Usage: $progname [host:port] [OPTIONS] [-- command args]
24+
25+
-h | --host Host or IP under test
26+
-p | --port TCP port under test
27+
Alternatively, you can specify the host and port as host:port
28+
-d | --delay Delay in seconds, before trying to contact the host.
29+
-m | --message Delay message
30+
-s | --strict Only execute subcommand if the test succeeds
31+
-q | --quiet Don't output any status messages
32+
-t | --timeout Timeout in seconds, zero for no timeout
33+
34+
-- command args Execute command with args after the test finishes
35+
36+
Examples:
37+
$progname mysql:3306 Wait indefinitely for port 3306 to be available on host mysql
38+
$progname google.com:80 Wait indefinitely for port 80 to be available on host google.com
39+
$progname mysql:3306 -t 15 Wait a maximum of 15s for port 3306 to be available on host mysql
40+
41+
Use echo \$? to get the result
42+
43+
Full example:
44+
$progname mysql:3306 \\
45+
-t 120 \\
46+
-d 2 \\
47+
-m 'Waiting for database connection on host:\$HOST and port:\$PORT' \\
48+
-s \\
49+
-- echo "Database connection established" \\
50+
|| echo "Error while trying to connect to the database"
51+
52+
Wait 120 seconds for port 3306 to be available on host mysql
53+
Display a custom message every 2 seconds
54+
Display a custom message on success
55+
Display a custom message on error (strict mode)
56+
57+
USAGE
58+
}
59+
60+
# echo the message if not in quiet mode
61+
function echoerr() {
62+
[ "$QUIET" -ne 1 ] && printf "%s\n" "$*" 1>&2
63+
}
64+
65+
function do_wait() {
66+
until nc -z "$HOST" "$PORT"; do
67+
result=$?
68+
echoerr "$MESSAGE"
69+
sleep $DELAY
70+
done
71+
72+
return $result
73+
}
74+
75+
function wait_for_host() {
76+
if [ "$TIMEOUT" -gt 0 ]; then
77+
# Waiting message
78+
echoerr "Waiting $TIMEOUT seconds for $HOST:$PORT"
79+
# trap SIGINT SIGTERM
80+
trap 'kill -SIGTERM $TIMEOUT_ID 2>/dev/null; return 1' SIGINT SIGTERM
81+
# use timeout function to rerun the script without timeout
82+
timeout -t "$TIMEOUT" -s TERM "$0" -h=$HOST -p=$PORT -d=$DELAY -m="$MESSAGE" -s=$STRICT -q=$QUIET -t=0 &
83+
# get the process id
84+
TIMEOUT_ID=$!
85+
# wait to the end of the timeout unless it is killed
86+
while kill -0 $TIMEOUT_ID > /dev/null 2>&1; do
87+
wait
88+
done
89+
# Last check to get an error at the end of the timeout
90+
nc -z "$HOST" "$PORT"
91+
result=$?
92+
else
93+
do_wait
94+
# get the result of the wait function
95+
result=$?
96+
fi
97+
98+
return $result
99+
}
100+
101+
# Default values
102+
STRICT=0
103+
QUIET=0
104+
TIMEOUT=0
105+
DELAY=2
106+
MESSAGE='Waiting connection for $HOST:$PORT'
107+
108+
# Get input parameters
109+
while [ $# -gt 0 ]; do
110+
case "$1" in
111+
112+
[!-]*:* )
113+
THOST=$(printf "%s\n" "$1"| cut -d : -f 1)
114+
TPORT=$(printf "%s\n" "$1"| cut -d : -f 2)
115+
[ -z "$HOST" ] && HOST=$THOST
116+
case $TPORT in
117+
''|*[!0-9]*) break ;;
118+
*) [ -z "$PORT" ] && PORT=$TPORT ;;
119+
esac
120+
shift 1
121+
;;
122+
123+
-h|--host)
124+
HOST="$2"
125+
[ -z "$HOST" ] && break
126+
shift 2
127+
;;
128+
129+
-h=*|--host=*)
130+
HOST=$(printf "%s" "$1" | cut -d = -f 2)
131+
shift 1
132+
;;
133+
134+
-p|--port)
135+
case $2 in
136+
''|*[!0-9]*) break ;;
137+
*) PORT="$2" ;;
138+
esac
139+
shift 2
140+
;;
141+
142+
-p=*|--port=*)
143+
case ${1#*=} in
144+
''|*[!0-9]*) break ;;
145+
*) PORT="${1#*=}" ;;
146+
esac
147+
shift 1
148+
;;
149+
150+
-d|--delay)
151+
case $2 in
152+
''|*[!0-9]*) break ;;
153+
*) DELAY="$2" ;;
154+
esac
155+
shift 2
156+
;;
157+
158+
-d=*|--delay=*)
159+
case ${1#*=} in
160+
''|*[!0-9]*) break ;;
161+
*) DELAY="${1#*=}" ;;
162+
esac
163+
shift 1
164+
;;
165+
166+
-m|--message)
167+
MESSAGE="$2"
168+
shift 2
169+
;;
170+
171+
-m=*|--message=*)
172+
MESSAGE=$(printf "%s" "$1" | cut -d = -f 2)
173+
shift 1
174+
;;
175+
176+
-s|--strict)
177+
STRICT=1
178+
shift 1
179+
;;
180+
181+
-s=*|--strict=*)
182+
case ${1#*=} in
183+
''|[!0-1]) break ;;
184+
*) STRICT="${1#*=}" ;;
185+
esac
186+
shift 1
187+
;;
188+
189+
-q|--quiet)
190+
QUIET=1
191+
shift 1
192+
;;
193+
194+
-q=*|--quiet=*)
195+
case ${1#*=} in
196+
''|[!0-1]) break ;;
197+
*) QUIET="${1#*=}" ;;
198+
esac
199+
shift 1
200+
;;
201+
202+
-t|--timeout)
203+
case $2 in
204+
''|*[!0-9]*) break ;;
205+
*) TIMEOUT="$2" ;;
206+
esac
207+
shift 2
208+
;;
209+
210+
-t=*|--timeout=*)
211+
case ${1#*=} in
212+
''|*[!0-9]*) break ;;
213+
*) TIMEOUT="${1#*=}" ;;
214+
esac
215+
shift 1
216+
;;
217+
218+
--)
219+
shift
220+
break
221+
;;
222+
223+
--help)
224+
getHelp
225+
exit 0
226+
;;
227+
228+
*)
229+
echoerr "Invalid argument '$1'. Use --help to see the valid options"
230+
exit 1
231+
;;
232+
233+
esac
234+
done
235+
236+
# check for host and port
237+
if [ -z "$HOST" -o -z "$PORT" ]; then
238+
echoerr "Invalid host or port. Use --help to see the valid options."
239+
exit 2
240+
fi
241+
242+
# Update the HOST and PORT in the default message
243+
MESSAGE=$(eval "echo $MESSAGE")
244+
245+
# Start waiting for the host
246+
wait_for_host
247+
WAIT_RESULT=$?
248+
249+
# If not in strict mode, execute the subcommand whatever
250+
# the result of wait_for_host
251+
if [ "$*" != "" ]; then
252+
if [ $WAIT_RESULT -ne 0 -a $STRICT -eq 1 ]; then
253+
echoerr "Error while in strict mode. Refusing to execute subcommand"
254+
else
255+
exec "$@"
256+
fi
257+
fi
258+
259+
# Exit with the result of wait_for_host
260+
exit $WAIT_RESULT

0 commit comments

Comments
 (0)