I want to send a PING to Redis to check if the connection is working, now I could just install redis-cli, but I don't want to and curl is already there. So how can I abuse curl to do that? Basically I need to turn off what's send here:

This worked for me, super helpful. Can you explain what's going on with those angle brackets? I'm not sure what to begin googling to find out what those are.
– Eric HuDec 19 '16 at 12:28

2

@EricHu 3<> Is opening file descriptor 3 as read-write to the file /dev/tcp/127.0.0.1/6379 then >&3 redirects stdout from the echo to FD3 and <&3 redirects stdin from FD3 into head.
– Aaron McMillinSep 8 '17 at 17:32

REDIS_HOST = host name (DNS address or IP) containing the redis master and sentinel
(break this into separate hosts if they're separate, and change the ports
if you need to - but in the helm chart the master/slave and sentinel are
in the same pod and use the standard ports)

The intricacies of the technique are described in the comments (I suggest you keep the comments in place to save your colleagues - and future self - from certain madness when trying to decipher the angle brackets)

# wait for 10 mins and check again every 15 seconds
let n=${REDIS_STARTUP_TIMEOUT:-600}
let m=${REDIS_STARTUP_RETRY:-15}
ready=false
while ((n > 0)); do
# These scripts are the best way to check if redis is running without having access to nc, curl or redis-cli
# They write a "PING" to the redis and sentinel ports on the hostname "dc-ecm-redis-ha"
# and look for a "PONG+" in return.
#
# Detailed explanation:
# - 3<>/dev/tcp... opens a file handle identified as #3 for input and output on the tcp host and port
# The host $REDIS_HOST is defined in DNS by the Kubernetes _service_, and the port is for redis or sentinel
# (Uses linux's low-level network-as-filesystem support. Think of it as a sort of poor-man's telnet)
# - "PING" followed by carriage-return is sent to the port by redirecting to the handle with >&3
# - The response from the port is sent to the head command with <&3
# - The first 5 bytes of the response are captured with -c 5. This removes the linebreak (\r) from the response
# - Standard shell $() around the whole thing stores the result in a variable (master or sentinel)
# - When Redis is NOT ready, the result is generally a failure in the exec or some other error, which goes
# to stderr, so we wrap it in { } > 2>&1 to capture that error in the variable too.
# - Success is measured by "+PONG" being in the variable
# - If you set the variable DEBUG to "true" (or "TRUE" -> the {,,} lower-cases it) the failed responses are echoed
# - (There are easier ways to do this if you have redis-cli installed or nc, but typically you don't on a docker container)
# - The whole thing waits n seconds for Redis to be ready, checking every m seconds
#
master=$( { exec 3<>/dev/tcp/${REDIS_HOST}/6379 && echo -e "PING\r\n" >&3 && head -c 5 <&3; } 2>&1 )
sentinel=$( { exec 3<>/dev/tcp/${REDIS_HOST}/26379 && echo -e "PING\r\n" >&3 && head -c 5 <&3; } 2>&1 )
if [ "$sentinel" = "+PONG" -a "$master" = "+PONG" ]; then ready=true;
break;
else echo "$(date) : Waiting $n more seconds for Redis master and sentinel to respond to PING"
[[ "${DEBUG,,}" = "true" ]] && echo "master response was [$master]";
[[ "${DEBUG,,}" = "true" ]] && echo "sentinel response was [$sentinel]";
sleep $m
((n-=m))
fi
done
if [ "$ready" = true ]
then echo "$(date) : REDIS is ready"
# do something when Redis is ready
else
echo "$(date) : ERROR: REDIS is still not ready. Giving up waiting"
# do something when Redis fails
fi