#!/bin/bash # (1) Init. #--------------------------------------------------------# # (1) Get current absolute dir ROOT=$(dirname `realpath $0`); # (2) Check argc test $# -lt 2 && echo -e "error: too fewarguments\n\n\e[1mUSAGE\e[0m\n\tpool \n\n\e[1mARGUMENTS\e[0m\n\t\tThe key of the pool (client must match it)\n\t\tTo port to listen to\n" && exit 1; # (3) Check @PORT range # MIN_PORT=1024; MAX_PORT=49151; test "$2" -gt "$MAX_PORT" -o "$2" -lt "$MIN_PORT" && echo "error: must be between $MIN_PORT and $MAX_PORT" && exit 1; # (4) Set argument explicit names # POOL_KEY="$1"; POOL_PORT="$2"; # (5) init logger variables # declare -A INPUT_PID; # will contain each bind-input pid # (6) Define on-exit routine # LOOP_PID=""; on_exit(){ echo "- killing 'pool' loop"; kill -INT $LOOP_PID 2>/dev/null; echo "- killing ${#INPUT_PID[@]} background listeners"; for logger_name in "${!INPUT_PID[@]}"; do # kill each logger input echo " - killing input@$logger_name (${INPUT_PID[$logger_name]})"; test ! -z "${INPUT_PID[$logger_name]}" && kill -INT ${INPUT_PID[$logger_name]} 2>/dev/null; done; echo "- killing 'pool' input listener ($POOL_PID)"; kill -INT $POOL_PID 2>/dev/null; exit 1; } # (2) Launch pool listener #--------------------------------------------------------# # (1) Bind-input # echo "+ listen $POOL_PORT"; POOL_PID="`$ROOT/bind-input pool $POOL_PORT`"; # (4) Launch pool manager #--------------------------------------------------------# # infinite listener PORT="$MIN_PORT"; ( trap "on_exit;" HUP INT KILL TERM; while true; do # Listen on port @POOL_PORT MSG=`$ROOT/read pool`; # Do nothing if empty msg or invalid format test -z "$MSG" && sleep .5 && continue; echo " + received '$MSG'"; echo -n "$MSG" | grep -vP '^([^:]+):([^:]+):([^:]+):([^:]+)$' >/dev/null && echo ' + invalid format' && sleep .5 && continue; # Extract ID - PORT KEY="`echo -ne \"$MSG\" | sed 's/^\(.\+\):\(.\+\):\(.\+\):\(.\+\)$/\1/'`"; LOGGER_NAME="`echo -ne \"$MSG\" | sed 's/^\(.\+\):\(.\+\):\(.\+\):\(.\+\)$/\2/'`"; LOGGER_HOST="`echo -ne \"$MSG\" | sed 's/^\(.\+\):\(.\+\):\(.\+\):\(.\+\)$/\3/'`"; LOGGER_PORT="`echo -ne \"$MSG\" | sed 's/^\(.\+\):\(.\+\):\(.\+\):\(.\+\)$/\4/'`"; # if ID does not match test "$KEY" != "$POOL_KEY" && echo ' + wrong id' && sleep .5 && continue; # create new listening socket echo " + received logger: $LOGGER_NAME on $LOGGER_HOST:$LOGGER_PORT"; # Find an available port PORT="`expr $PORT + 1`"; while true; do # ignore pool port test "$PORT" = "$POOL_PORT" && PORT="`expr $PORT + 1`" && continue; # if port not in use -> use it ss -tl4 "( sport = :$PORT )" | grep "$PORT" >/dev/null 2>&1 || break; # else try next port (+1) PORT="`expr $PORT + 1`"; done; # if already an input for this logger -> kill it if [ ! -z "${INPUT_PID[$LOGGER_NAME]}" ]; then echo " + already an input -> killing it"; kill -INT ${INPUT_PID[$LOGGER_NAME]}; fi; # Bind-input for the logger at the free port found # Store bind-input PID echo " + listen $PORT"; INPUT_PID["$LOGGER_NAME"]="`$ROOT/bind-input $LOGGER_NAME $PORT`"; # Notify that input is active to MASTER echo " + sending back to port '$PORT' $LOGGER_HOST:$LOGGER_PORT"; bash -c "exec 4<>/dev/tcp/$LOGGER_HOST/$LOGGER_PORT; echo -n \"$PORT\" >&4;"; echo " + background process"; done; )& LOOP_PID=$!; # (3) Set exit management #--------------------------------------------------------# trap "kill -INT $LOOP_PID;" HUP INT KILL TERM; wait $LOOP_PID;