99 lines
2.7 KiB
Bash
Executable File
99 lines
2.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
|
|
# Following regex is based on https://tools.ietf.org/html/rfc3986#appendix-B with
|
|
# additional sub-expressions to split authority into userinfo, host and port
|
|
#
|
|
readonly URI_REGEX='^(([^:/?#]+):)?(//((([^:/?#]+)?(:([^:/?#]+))?@)?([^:/?#]+)(:([0-9]+))?))(/([^?#]*))?(\?([^#]*))?(#(.*))?'
|
|
# ↑↑ ↑ ↑↑↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
|
|
# |2 scheme | ||6 userinfo passwd 7 host | 9 port | 11 rpath | 13 query | 15 fragment
|
|
# 1 scheme: | |5 userinfo@ 8 :… 10 path 12 ?… 14 #…
|
|
# | 4 authority
|
|
# 3 //…
|
|
IDX_SCHEME=2
|
|
IDX_USER=6
|
|
IDX_PASSWD=8
|
|
IDX_HOST=9
|
|
IDX_PORT=11
|
|
IDX_PATH=12
|
|
IDX_RPATH=13
|
|
IDX_QUERY=15
|
|
IDX_FRAGMENT=17
|
|
|
|
# processing argument
|
|
POSITIONAL=()
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-s|--ssh)
|
|
SSH="$2"
|
|
shift
|
|
shift
|
|
;;
|
|
--)
|
|
shift
|
|
POSITIONAL+=("$@")
|
|
break
|
|
;;
|
|
*)
|
|
POSITIONAL+=("$1")
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
set -- "${POSITIONAL[@]}"
|
|
|
|
# check arguments
|
|
if [[ $# == 0 ]]; then
|
|
echo "Usage: $0 [-s|--ssh SSH_DESTINATION] <REDIS_URI> [...REDIS_CLI_ARGS]"
|
|
echo " -s, --ssh for ssh tunnel"
|
|
echo " REDIS_URI redis://:passwd@host:port/db"
|
|
exit -1
|
|
fi
|
|
# pop the REDIS_URI and process it
|
|
if [[ ! ($1 =~ $URI_REGEX) ]]; then
|
|
echo "Invalid redis uri"
|
|
exit -1
|
|
fi
|
|
shift
|
|
|
|
SCHEME=${BASH_REMATCH[$IDX_SCHEME]}
|
|
USER=${BASH_REMATCH[$IDX_USER]}
|
|
PASSWD=${BASH_REMATCH[$IDX_PASSWD]}
|
|
HOST=${BASH_REMATCH[$IDX_HOST]}
|
|
PORT=${BASH_REMATCH[$IDX_PORT]}
|
|
UPATH=${BASH_REMATCH[$IDX_PATH]}
|
|
RPATH=${BASH_REMATCH[$IDX_RPATH]}
|
|
QUERY=${BASH_REMATCH[$IDX_QUERY]}
|
|
FRAGMENT=${BASH_REMATCH[$IDX_FRAGMENT]}
|
|
|
|
# create ssh tunnel if `--ssh` is assigned
|
|
is-port-used() {
|
|
lsof -i -P -n | awk '{print $9}' | grep -F ":$1" >/dev/null
|
|
}
|
|
|
|
if [[ -n $SSH ]]; then
|
|
# find available
|
|
read lower_port upper_port < /proc/sys/net/ipv4/ip_local_port_range
|
|
while :; do
|
|
for (( port = lower_port ; port <= upper_port ; port++ )); do
|
|
! is-port-used $port && break 2
|
|
done
|
|
done
|
|
|
|
# forward local port to remote destination
|
|
ssh -N -L localhost:$port:$HOST:$PORT $SSH &
|
|
SSH_PID=$!
|
|
# wait until port is ready
|
|
while ! is-port-used $port; do
|
|
sleep 0.1
|
|
done
|
|
|
|
HOST=localhost
|
|
PORT=$port
|
|
fi
|
|
|
|
redis-cli -h "$HOST" -p "${PORT-6379}" -a "$PASSWD" -n "${RPATH-0}" "$@"
|
|
|
|
# clean up ssh connection
|
|
[[ -n $SSH_PID ]] && kill -9 $SSH_PID
|