#!/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 # (2) Set exit management #--------------------------------------------------------# # (1) On-Exit routine # on_exit(){ echo "killing 'bind-input' sub processes"; for logger_name in "${!INPUT_PID[@]}"; do # kill each logger input kill -9 ${INPUT_PID[$logger_name]} 2>/dev/null; $INPUT_PID[$logger_name]=""; done; echo "killing 'pool' input listener"; kill -9 $POOL_PID 2>/dev/null; echo "killing 'pool' loop"; kill -9 $LOOP_PID 2>/dev/null; } trap "on_exit;" INT KILL; # (3) Launch pool listener #--------------------------------------------------------# # (1) Bind-input # echo "(.) listen $POOL_PORT"; $ROOT/bind-input pool $POOL_PORT& POOL_PID=$?; # (4) Launch pool manager #--------------------------------------------------------# # infinite listener while sleep 1; do # Listen on port @POOL_PORT MSG=`$ROOT/read pool`; # Do nothing if empty msg or invalid format test -z "$MSG" && continue; echo -n "$MSG" | grep -vP '^([^:]+):([^:]+):([^:]+):([^:]+)$' >/dev/null && echo ' /!\\ invalid format' && 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' && continue; # create new listening socket echo " (.) binding input for logger@$LOGGER_NAME ($LOGGER_HOST:$LOGGER_PORT)"; # Find an available port PORT="$MIN_PORT"; 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; # Bind-input for the logger at the free port found $ROOT/bind-input $LOGGER_NAME $PORT& # if already an input for this logger -> kill it test ! -z "${INPUT_PID[$LOGGER_NAME]}" && kill -9 ${INPUT_PID[$LOGGER_NAME]}; # Store bind-input PID INPUT_PID[LOGGER_NAME]=$!; # Notify that input is active to MASTER bash -c "exec 4<>/dev/tcp/$LOGGER_HOST/$LOGGER_PORT; echo -n \"$PORT\" >&4;"; done& LOOP_PID=$!; wait $LOOP_PID;