wait-for-it.sh 5.2 KB

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