2018-01-30 16:00:11 +00:00
#!/bin/bash
# (1) Init.
#--------------------------------------------------------#
# (1) Get current absolute dir
ROOT=$(dirname `realpath $0`);
# (2) Check argc
2018-01-30 17:50:44 +00:00
test $# -lt 2 && echo -e "error: too fewarguments\n\n\e[1mUSAGE\e[0m\n\tpool <key> <port>\n\n\e[1mARGUMENTS\e[0m\n\t<key>\tThe key of the pool (client must match it)\n\t<port>\tTo port to listen to\n" && exit 1;
2018-01-30 16:00:11 +00:00
# (3) Check @PORT range #
2018-01-30 17:50:44 +00:00
MIN_PORT=1024;
MAX_PORT=49151;
2018-01-30 16:00:11 +00:00
test "$2" -gt "$MAX_PORT" -o "$2" -lt "$MIN_PORT" && echo "error: <port> must be between $MIN_PORT and $MAX_PORT" && exit 1;
# (4) Set argument explicit names #
2018-01-30 17:50:44 +00:00
POOL_KEY="$1";
POOL_PORT="$2";
2018-01-30 16:00:11 +00:00
2018-02-01 12:35:19 +00:00
# (5) Create a temporary file #
TMPFILE="/dev/shm/pool_pid";
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# (6) Define on-exit routine #
LOOP_PID="";
2018-01-30 17:50:44 +00:00
on_exit(){
2018-02-01 12:35:19 +00:00
test -f /dev/shm/pool_input_pid && source /dev/shm/pool_input_pid && rm /dev/shm/pool_input_pid;
2018-01-30 17:50:44 +00:00
2018-02-01 12:35:19 +00:00
echo "- killing oop";
2018-01-31 19:55:11 +00:00
kill -INT $LOOP_PID 2>/dev/null;
2018-02-01 12:35:19 +00:00
echo "- killing ${#INPUT_PID[@]} loggers";
2018-01-30 17:50:44 +00:00
for logger_name in "${!INPUT_PID[@]}"; do
# kill each logger input
2018-02-01 12:35:19 +00:00
echo " - killing $logger_name (${INPUT_PID[$logger_name]})";
2018-01-31 19:55:11 +00:00
test ! -z "${INPUT_PID[$logger_name]}" && kill -INT ${INPUT_PID[$logger_name]} 2>/dev/null;
2018-01-30 17:50:44 +00:00
done;
2018-02-01 12:35:19 +00:00
echo "- killing main listener ($POOL_PID)";
2018-01-31 19:55:11 +00:00
kill -INT $POOL_PID 2>/dev/null;
2018-01-30 17:50:44 +00:00
2018-02-01 12:35:19 +00:00
# delete tmp file
echo "- deleting tmp file";
rm $TMPFILE 2>/dev/null;
2018-01-31 19:55:11 +00:00
exit 1;
2018-01-30 17:50:44 +00:00
}
2018-01-31 19:55:11 +00:00
# (2) Launch pool listener
2018-01-30 16:00:11 +00:00
#--------------------------------------------------------#
2018-01-30 17:50:44 +00:00
# (1) Bind-input #
2018-02-01 12:35:19 +00:00
echo -e "\e[32m+\e[0m listen $POOL_PORT";
$ROOT/bind-input pool $POOL_PORT > $TMPFILE;
POOL_PID="`cat $TMPFILE`";
2018-01-30 17:50:44 +00:00
2018-01-30 16:00:11 +00:00
2018-02-01 12:35:19 +00:00
# (3) Launch pool manager
2018-01-30 17:50:44 +00:00
#--------------------------------------------------------#
2018-01-30 16:00:11 +00:00
# infinite listener
2018-01-31 19:55:11 +00:00
(
2018-02-01 12:35:19 +00:00
USED_PORTS=($POOL_PORT);
declare -A INPUT_PID; # will contain each bind-input pid
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
trap "on_exit;" HUP INT KILL TERM;
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
while true; do
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# Listen on port @POOL_PORT
MSG=`$ROOT/read pool`;
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# Do nothing if empty msg or invalid format
test -z "$MSG" && sleep .5 && continue;
2018-01-31 23:31:21 +00:00
2018-02-01 12:35:19 +00:00
echo -e " + received '\e[33m$MSG\e[0m'";
# check if END msg
test "$MSG" = "END${POOL_KEY}END" && echo -e "\e[31m+\e[0m stop listening on $POOL_PORT" && break;
# check format
2018-01-31 23:31:21 +00:00
echo -n "$MSG" | grep -vP '^([^:]+):([^:]+):([^:]+):([^:]+)$' >/dev/null && echo ' + invalid format' && sleep .5 && continue;
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# 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/'`";
2018-01-30 16:00:11 +00:00
2018-02-01 12:35:19 +00:00
# check port format
echo -n "$LOGGER_PORT" | grep -vP "^\d+$" >/dev/null && echo ' + invalid format: NaN' && sleep .5 && continue;
2018-01-31 19:55:11 +00:00
# if ID does not match
2018-01-31 23:31:21 +00:00
test "$KEY" != "$POOL_KEY" && echo ' + wrong id' && sleep .5 && continue;
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# create new listening socket
2018-02-01 12:35:19 +00:00
echo " + new logger '$LOGGER_NAME' from $LOGGER_HOST";
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# Find an available port
2018-02-01 12:35:19 +00:00
PORT="$MIN_PORT";
2018-01-31 19:55:11 +00:00
while true; do
2018-01-30 16:00:11 +00:00
2018-02-01 15:06:40 +00:00
# do not use same port as master (if on same machine)
test "$PORT" = "$LOGGER_PORT" && PORT="`expr $PORT + 1`" && continue;
2018-02-01 12:35:19 +00:00
# ignore already used ports
for used in ${USED_PORTS[*]}; do
test "$PORT" = "$used" && PORT="`expr $PORT + 1`" && continue;
done
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
# 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`";
2018-01-30 16:00:11 +00:00
2018-01-31 19:55:11 +00:00
done;
2018-01-30 17:50:44 +00:00
2018-01-31 19:55:11 +00:00
# if already an input for this logger -> kill it
2018-01-31 23:31:21 +00:00
if [ ! -z "${INPUT_PID[$LOGGER_NAME]}" ]; then
echo " + already an input -> killing it";
kill -INT ${INPUT_PID[$LOGGER_NAME]};
fi;
2018-01-30 17:50:44 +00:00
2018-01-31 19:55:11 +00:00
# Bind-input for the logger at the free port found
# Store bind-input PID
2018-02-01 12:35:19 +00:00
echo -e " \e[32m+\e[0m listen $PORT ($LOGGER_NAME)";
$ROOT/bind-input $LOGGER_NAME $PORT > $TMPFILE;
INPUT_PID["$LOGGER_NAME"]="`cat $TMPFILE`";
declare -p INPUT_PID > /dev/shm/pool_input_pid;
# add @PORT to used ports
USED_PORTS="$USED_PORTS $PORT";
2018-01-31 23:31:21 +00:00
2018-01-30 17:50:44 +00:00
2018-01-31 19:55:11 +00:00
# Notify that input is active to MASTER
2018-02-01 15:06:40 +00:00
sleep 1;
2018-02-01 12:35:19 +00:00
echo " + sending '$PORT' to $LOGGER_HOST:$LOGGER_PORT";
2018-01-31 19:55:11 +00:00
bash -c "exec 4<>/dev/tcp/$LOGGER_HOST/$LOGGER_PORT; echo -n \"$PORT\" >&4;";
2018-01-30 17:50:44 +00:00
2018-01-31 23:31:21 +00:00
echo " + background process";
2018-01-31 19:55:11 +00:00
done;
)&
2018-01-30 17:50:44 +00:00
LOOP_PID=$!;
2018-01-30 16:00:11 +00:00
2018-02-01 12:35:19 +00:00
# (4) Set exit management
2018-01-31 19:55:11 +00:00
#--------------------------------------------------------#
2018-02-01 12:35:19 +00:00
# (1) Set trap for "exit" signals #
trap "kill -INT $LOOP_PID 2>/dev/null;" HUP INT KILL TERM;
2018-01-31 19:55:11 +00:00
2018-02-01 12:35:19 +00:00
# (2) Wait for main loop to end
2018-01-30 17:50:44 +00:00
wait $LOOP_PID;
2018-01-30 16:00:11 +00:00
2018-02-01 12:35:19 +00:00
# (3) Wait for each daemon input to end #
test -f /dev/shm/pool_input_pid && source /dev/shm/pool_input_pid;
echo " + ${#INPUT_PID[@]} loggers running in background";
for logger_name in "${!INPUT_PID[@]}"; do
while [ -e /proc/${INPUT_PID[$logger_name]} ]; do
sleep .5
done
echo " + $logger_name terminated (${INPUT_PID[$logger_name]})";
done;
on_exit;