1
+ #! /usr/bin/env bash
2
+ # Use this script to test if a given TCP host/port are available
3
+
4
+ WAITFORIT_cmdname=${0##*/ }
5
+
6
+ echoerr () { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo " $@ " 1>&2 ; fi }
7
+
8
+ usage ()
9
+ {
10
+ cat << USAGE >&2
11
+ Usage:
12
+ $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args]
13
+ -h HOST | --host=HOST Host or IP under test
14
+ -p PORT | --port=PORT TCP port under test
15
+ Alternatively, you specify the host and port as host:port
16
+ -s | --strict Only execute subcommand if the test succeeds
17
+ -q | --quiet Don't output any status messages
18
+ -t TIMEOUT | --timeout=TIMEOUT
19
+ Timeout in seconds, zero for no timeout
20
+ -- COMMAND ARGS Execute command with args after the test finishes
21
+ USAGE
22
+ exit 1
23
+ }
24
+
25
+ wait_for ()
26
+ {
27
+ if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
28
+ echoerr " $WAITFORIT_cmdname : waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST :$WAITFORIT_PORT "
29
+ else
30
+ echoerr " $WAITFORIT_cmdname : waiting for $WAITFORIT_HOST :$WAITFORIT_PORT without a timeout"
31
+ fi
32
+ WAITFORIT_start_ts=$( date +%s)
33
+ while :
34
+ do
35
+ if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then
36
+ nc -z $WAITFORIT_HOST $WAITFORIT_PORT
37
+ WAITFORIT_result=$?
38
+ else
39
+ (echo -n > /dev/tcp/$WAITFORIT_HOST /$WAITFORIT_PORT ) > /dev/null 2>&1
40
+ WAITFORIT_result=$?
41
+ fi
42
+ if [[ $WAITFORIT_result -eq 0 ]]; then
43
+ WAITFORIT_end_ts=$( date +%s)
44
+ echoerr " $WAITFORIT_cmdname : $WAITFORIT_HOST :$WAITFORIT_PORT is available after $(( WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds"
45
+ break
46
+ fi
47
+ sleep 1
48
+ done
49
+ return $WAITFORIT_result
50
+ }
51
+
52
+ wait_for_wrapper ()
53
+ {
54
+ # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692
55
+ if [[ $WAITFORIT_QUIET -eq 1 ]]; then
56
+ timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
57
+ else
58
+ timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT &
59
+ fi
60
+ WAITFORIT_PID=$!
61
+ trap " kill -INT -$WAITFORIT_PID " INT
62
+ wait $WAITFORIT_PID
63
+ WAITFORIT_RESULT=$?
64
+ if [[ $WAITFORIT_RESULT -ne 0 ]]; then
65
+ echoerr " $WAITFORIT_cmdname : timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST :$WAITFORIT_PORT "
66
+ fi
67
+ return $WAITFORIT_RESULT
68
+ }
69
+
70
+ # process arguments
71
+ while [[ $# -gt 0 ]]
72
+ do
73
+ case " $1 " in
74
+ * :* )
75
+ WAITFORIT_hostport=(${1//:/ } )
76
+ WAITFORIT_HOST=${WAITFORIT_hostport[0]}
77
+ WAITFORIT_PORT=${WAITFORIT_hostport[1]}
78
+ shift 1
79
+ ;;
80
+ --child)
81
+ WAITFORIT_CHILD=1
82
+ shift 1
83
+ ;;
84
+ -q | --quiet)
85
+ WAITFORIT_QUIET=1
86
+ shift 1
87
+ ;;
88
+ -s | --strict)
89
+ WAITFORIT_STRICT=1
90
+ shift 1
91
+ ;;
92
+ -h)
93
+ WAITFORIT_HOST=" $2 "
94
+ if [[ $WAITFORIT_HOST == " " ]]; then break ; fi
95
+ shift 2
96
+ ;;
97
+ --host=* )
98
+ WAITFORIT_HOST=" ${1#* =} "
99
+ shift 1
100
+ ;;
101
+ -p)
102
+ WAITFORIT_PORT=" $2 "
103
+ if [[ $WAITFORIT_PORT == " " ]]; then break ; fi
104
+ shift 2
105
+ ;;
106
+ --port=* )
107
+ WAITFORIT_PORT=" ${1#* =} "
108
+ shift 1
109
+ ;;
110
+ -t)
111
+ WAITFORIT_TIMEOUT=" $2 "
112
+ if [[ $WAITFORIT_TIMEOUT == " " ]]; then break ; fi
113
+ shift 2
114
+ ;;
115
+ --timeout=* )
116
+ WAITFORIT_TIMEOUT=" ${1#* =} "
117
+ shift 1
118
+ ;;
119
+ --)
120
+ shift
121
+ WAITFORIT_CLI=(" $@ " )
122
+ break
123
+ ;;
124
+ --help)
125
+ usage
126
+ ;;
127
+ * )
128
+ echoerr " Unknown argument: $1 "
129
+ usage
130
+ ;;
131
+ esac
132
+ done
133
+
134
+ if [[ " $WAITFORIT_HOST " == " " || " $WAITFORIT_PORT " == " " ]]; then
135
+ echoerr " Error: you need to provide a host and port to test."
136
+ usage
137
+ fi
138
+
139
+ WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:- 15}
140
+ WAITFORIT_STRICT=${WAITFORIT_STRICT:- 0}
141
+ WAITFORIT_CHILD=${WAITFORIT_CHILD:- 0}
142
+ WAITFORIT_QUIET=${WAITFORIT_QUIET:- 0}
143
+
144
+ # Check to see if timeout is from busybox?
145
+ WAITFORIT_TIMEOUT_PATH=$( type -p timeout)
146
+ WAITFORIT_TIMEOUT_PATH=$( realpath $WAITFORIT_TIMEOUT_PATH 2> /dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH )
147
+
148
+ WAITFORIT_BUSYTIMEFLAG=" "
149
+ if [[ $WAITFORIT_TIMEOUT_PATH =~ " busybox" ]]; then
150
+ WAITFORIT_ISBUSY=1
151
+ # Check if busybox timeout uses -t flag
152
+ # (recent Alpine versions don't support -t anymore)
153
+ if timeout & > /dev/stdout | grep -q -e ' -t ' ; then
154
+ WAITFORIT_BUSYTIMEFLAG=" -t"
155
+ fi
156
+ else
157
+ WAITFORIT_ISBUSY=0
158
+ fi
159
+
160
+ if [[ $WAITFORIT_CHILD -gt 0 ]]; then
161
+ wait_for
162
+ WAITFORIT_RESULT=$?
163
+ exit $WAITFORIT_RESULT
164
+ else
165
+ if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then
166
+ wait_for_wrapper
167
+ WAITFORIT_RESULT=$?
168
+ else
169
+ wait_for
170
+ WAITFORIT_RESULT=$?
171
+ fi
172
+ fi
173
+
174
+ if [[ $WAITFORIT_CLI != " " ]]; then
175
+ if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then
176
+ echoerr " $WAITFORIT_cmdname : strict mode, refusing to execute subprocess"
177
+ exit $WAITFORIT_RESULT
178
+ fi
179
+ exec " ${WAITFORIT_CLI[@]} "
180
+ else
181
+ exit $WAITFORIT_RESULT
182
+ fi
0 commit comments