1. Overview
In this tutorial, we’ll learn how to check the Redis server connection without using the redis-cli command-line tool.
2. Redis Communication Protocol
Redis is an in-memory data store that is often used as a cache or database. Its speed and scalability make it a popular choice as a cache provider.
The Redis server communicates in the Redis serialization protocol (RESP). Through the serialization protocol, we can send commands that Redis defines to perform an action on the data store.
For example, PING is one such command that the Redis service defines to allow the clients to test connections. If the server is working properly, it replies with a PONG message whenever clients send a PING request.
There are many more commands that the Redis service defines for other operations, such as SET, GET, and EXISTS. For more information on the commands, we can refer to the Redis official documentation.
Additionally, Redis uses the TCP protocol as its network layer for delivering the commands and responses between client and server. While there’s a comprehensive client tool for Redis, the redis-cli, sometimes we might find ourselves unable to use it. One such example is when we’re in a highly minimized container image that doesn’t allow the installation of arbitrary command-line tools. In those scenarios, it can be difficult to perform some connectivity tests to a Redis server.
Ultimately, without the redis-cli tool, we’ll have to resort to tools that can send a raw TCP message. This automatically disqualifies pure HTTP clients such as wget as it always sends the messages with HTTP-specific boilerplates.
In the following sections, we’ll look at several such tools that allow us to send raw TCP messages to a Redis service.
3. Sending TCP Message With nc
The nc command, also known as the netcat, is a versatile networking command-line tool. It’s primarily used for starting a TCP/UDP server and as a TCP/UDP client.
Since it’s capable of sending raw TCP messages, we can use the nc tool to test the connectivity of a Redis server.
To obtain the nc command, we can install the netcat package using the package manager on our system:
$ apt-get install -y netcat
Once the installation is successful, we’re ready to send the PING command to the Redis service.
First, we establish a TCP connection to the Redis service by running nc and supplying the hostname and port number of the Redis service. Let’s connect to our Redis server running locally and listening on port 6379:
$ nc localhost 6379
If the command above returns immediately with an exit code of 1, it means the connection couldn’t be established. This happens when the target port doesn’t accept our TCP requests:
$ nc localhost 6379
$ echo $?
On the other hand, if the connection is successful, we’ll see that the command doesn’t return nor terminate. Instead, it’s in the state of waiting for input from the standard input stream.
At this point, we can confirm that port 6379 on localhost is listening to the TCP connection. However, we cannot be sure if the receiving end is actually a Redis server. To test it further, we can send a PING command on the standard input stream:
$ nc localhost 6379
ping
+PONG
From the standard output, we can see that the server responded to our PING request with the PONG response. This further confirms that the service we’ve connected to is indeed a properly working Redis server.
4. Using TELNET Protocol With telnet
The telnet command-line tool is another popular tool for network diagnostic purposes. Specifically, people commonly use the telnet command to verify that a port is accessible. Besides that, using telnet, we can send text messages to the remote service over the connection.
To connect to the Redis service, we can run the telnet command and specify the hostname and port of the Redis service:
$ telnet localhost 6379
The command always prints the first line of the diagnostic message, stating that it’s connecting to the hostname. Then, if the connection is successful, we’ll see two additional lines. Specifically, the first additional line confirms that we’re connected to the host:
$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Again, at this point, we can confirm that the Redis service is accessible on port 6379.
On the other hand, if the connection to the remote host fails, we’ll see the “Connection refused” error message on the standard error stream:
$ telnet localhost 6378
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused
Once the telnet command establishes the connection, we can send the PING command to the Redis service and observe the PONG response:
$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
ping
+PONG
Unfortunately, the telnet command line is commonly disabled on the system due to security concerns. Specifically, it doesn’t come with any security mechanism, unlike SSH.
If the command is unavailable, we can use the curl command to talk to the Redis service using the TELNET protocol.
5. Using TELNET Protocol With curl
The curl command is a popular command-line tool for transferring data to and from a server. It supports different protocols, such as HTTP, HTTPS, SCP, SFTP, and TELNET.
To know what protocol it should use when talking to the remote service, the curl command checks the protocol component of a URL. For example, if we run the curl command on https://www.google.com, it uses the HTTPS protocol to fetch the data from the www.google.com server.
To communicate with the Redis service using the TELNET protocol, we have to specify the TELNET protocol as the protocol component of the URL.
Concretely, we can establish a TELNET connection to the Redis service by running the curl command on telnet://localhost:6379:
$ curl -v telnet://localhost:6379
* Trying 127.0.0.1:6379...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 6379 (#0)
In the command above, we turn on the verbose mode of the curl command using the -v option. From the output, we can see that we’ve successfully connected to localhost at port 6379.
Once we’ve connected to the Redis service, we can send the PING request by typing the command onto the standard input and hitting the Enter key:
$ curl -v telnet://localhost:6379
* Trying 127.0.0.1:6379...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 6379 (#0)
ping
+PONG
6. Bash’s Built-in /dev/tcp File
In the Bash shell, the /dev/tcp/{host}/{port} device files are special files that we can use to open a TCP connection to a remote service. When we redirect the file to a file descriptor, Bash creates a TCP socket. Then, it connects the socket to the host and port according to the file path.
With the connection, we can send TCP messages to the remote service by writing to the file descriptor of the opened device file. Similarly, we can read the content of the file by reading the file descriptor associated with the file.
For example, we can redirect both the standard output and input streams of /dev/tcp/localhost/6379 to the file descriptor 3:
$ exec 3<>/dev/tcp/localhost/6379
The command above uses the Bash redirection operator <> to redirect both the standard input and output stream to the file descriptor 3. When we issue this command, Bash creates a TCP socket that connects to localhost on port 6379.
Then, we send the PING request to the Redis server by writing into the file descriptor 3:
$ echo -e "PING\r\n" >&3
The -e option causes the echo command to interpret the escape characters to ensure that we’re sending the carriage return to the server. When we run the command above, we’re writing the message PING\r\n to the file descriptor 3. The file descriptor 3 in turn redirects the message to the underlying TCP socket.
Finally, we can get the response from the remote service by reading the content of the file descriptor 3 using the cat command:
$ cat <&3
+PONG
Notably, the /dev/tcp device file doesn’t actually exist in the system. It’s a special file path that the Bash shell interprets to create a TCP socket.
If we run the commands above on a POSIX shell, we’ll get the “Directory nonexistent” instead:
$ sh
$ exec 3<>/dev/tcp/localhost/6379
sh: 1: cannot create /dev/tcp/localhost/6379: Directory nonexistent
$
7. Conclusion
In this article, we learned that the Redis communication protocol is TCP. We saw that this makes it difficult for diagnostic work in a constrained environment that doesn’t allow the installation of arbitrary command-line tools, such as redis-cli. We then looked at how to ping the Redis service with some other more commonly available tools.
Firstly, we saw how we can use the nc command-line tool to connect to a remote TCP service, such as Redis. Once the connection is established, we can send the Redis commands by entering them into the standard input stream. Besides that, we also learned that the telnet command-line tool can be used to send commands to the Redis service as well.
In a restrictive system, the nc and telnet commands might not be available. In those cases, we also discussed how we can use the curl command-line tool to send commands to the Redis service over the TELNET protocol.
Finally, we looked at the special /dev/tcp file in Bash that allows us to open a TCP socket to talk to a remote TCP server.