#!/usr/bin/env bash
# Use this script to test if a given TCP host/port are availablecmdname=$(basename $0)echoerr(){if[[$QUIET -ne 1]];thenecho"$@" 1>&2;fi}usage(){ cat << USAGE >&2
Usage:
$cmdname host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST Host or IP under test
-p PORT | --port=PORT TCP port under test
Alternatively, you specify the host and port as host:port
-s | --strict Only execute subcommand if the test succeeds
-q | --quiet Don't output any status messages
-t TIMEOUT | --timeout=TIMEOUT
Timeout in seconds, zero for no timeout
-- COMMAND ARGS Execute command with args after the test finishes
USAGEexit1}wait_for(){if[[$TIMEOUT -gt 0]];then echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT"else echoerr "$cmdname: waiting for $HOST:$PORT without a timeout"fistart_ts=$(date +%s)while :
do(echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1result=$?if[[$result -eq 0]];thenend_ts=$(date +%s) echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds"breakfi sleep 1donereturn$result}wait_for_wrapper(){# In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692if[[$QUIET -eq 1]];then timeout $TIMEOUT$0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT&else timeout $TIMEOUT$0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT&fiPID=$!trap"kill -INT -$PID" INT
wait$PIDRESULT=$?if[[$RESULT -ne 0]];then echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT"fireturn$RESULT}# process argumentswhile[[$# -gt 0]]docase"$1" in
*:* )hostport=(${1//:/ })HOST=${hostport[0]}PORT=${hostport[1]}shift1;; --child)CHILD=1shift1;; -q | --quiet)QUIET=1shift1;; -s | --strict)STRICT=1shift1;; -h)HOST="$2"if[[$HOST==""]];then break;fishift2;; --host=*)HOST="${1#*=}"shift1;; -p)PORT="$2"if[[$PORT==""]];then break;fishift2;; --port=*)PORT="${1#*=}"shift1;; -t)TIMEOUT="$2"if[[$TIMEOUT==""]];then break;fishift2;; --timeout=*)TIMEOUT="${1#*=}"shift1;; --)shiftCLI="$@"break;; --help) usage
;; *) echoerr "Unknown argument: $1" usage
;;esacdoneif[["$HOST"==""||"$PORT"==""]];then echoerr "Error: you need to provide a host and port to test." usage
fiTIMEOUT=${TIMEOUT:-15}STRICT=${STRICT:-0}CHILD=${CHILD:-0}QUIET=${QUIET:-0}if[[$CHILD -gt 0]];then wait_for
RESULT=$?exit$RESULTelseif[[$TIMEOUT -gt 0]];then wait_for_wrapper
RESULT=$?else wait_for
RESULT=$?fifiif[[$CLI !=""]];thenif[[$RESULT -ne 0&&$STRICT -eq 1]];then echoerr "$cmdname: strict mode, refusing to execute subprocess"exit$RESULTfiexec$CLIelseexit$RESULTfi