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