Find out how to talk to a Redis database with nothing more than echo and the netcat command and get a deeper understanding of why developers love Redis.
Redis has, as we've shown in the past, many many drivers. One of the reasons for situation is that, by design, Redis has a very simple protocol, RESP, for communicating with the server. Building on that simple protocol has allowed people to create these many drivers and their various levels of abstraction or idiomatic appropriateness. But let's talk about getting down to basics here; sometimes resource constraints demand you create the smallest possible connection code.
Our first command
For this example, we're going to get some status information from the Redis server; the INFO command returns lots of useful information so we will use that. Now, to send strings with Redis's RESP protocol, you need to say how long the string is. That's done by preceding your string with a
$ and the number of characters in the string so that's 4 characters. After the number and after the string should be the carriage return and newline,
\r\n. Let's build our string to send:
Redis's RESP also wants to know how many strings are in a command. It has a "bulk-strings" indicator which is like the
$ operator, except uses a
* and the number following it is the number of strings in the command. For this command, that's... 1. So we need to precede the string with
We can use the
nc - net cat - command to send this string to our server. That server, for this example is at sl-eu-lon-2-portal.1.dblayer.com and on port 10030. If we echo our string and pipe it into nc we should get information:
$ echo -e "*1\r\n$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030 -ERR Protocol error: expected '$', got ' ' $
The problem here is the old classic shell thing of unexpected expansion. The shell sees that $ and wants to expand it from an environment variable
$4 which is, of course, blank. We need to escape that and try again.
$ echo -e "*1\r\n\$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030 -NOAUTH Authentication required. $
Time to log on
Because who would put a completely open Redis server up on the internet. The Compose Redis servers start up with authentication on and a 16 character password set. If you are doing this against a server that you own and it worked, check now that that server isn't externally visible. Other people do not value your data. Anyway, back to getting authenicated. We need to construct another command, the
AUTH command and follow it with our password. This time, there's two strings in the command, the AUTH command itself and the password, let's say it's
FLIBBERTIGIBBETS for now. That gives us
*2\r\n\$4\r\nAUTH\r\n\$16\r\nFLIBBERTIGIBBETS\r\n which we can put into the front of out command now:
$ echo -e "*2\r\n\$4\r\nAUTH\r\n\$16\r\nFLIBBERTIGIBBETS\r\n*1\r\n\$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030 +OK $2306 # Server redis_version:3.2.6 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:dafadbf6141a77d5 redis_mode:standalone os:Linux 3.19.0-39-generic x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.8.4 process_id:36 run_id:275d6af5f6ccf9be4efde1dbcb8223483386cf42 tcp_port:6379 ... $
That goes on for a little while... There are 2,306 characters of information in total. We know that because that's the first thing Redis told us. In the same way, as we tell it how long strings are, it does the same back, so the second line,
$2306 is telling us how many characters are coming back. That's the response to the
INFO command. Immediately preceding that is
+OK, the response to the
AUTH command. The
+ is the signal that this is a simple non-binary safe string; a minimal OK.
Let's make it tidy
Anyway now we can pipe those results to any command we want for post-processing. Add a
| tail -n +3 to chop off the Redis RESP responses and we have a clean output, just like entering
INFO at the redis-cli command line. We're good people and good people don't leave passwords in shell scripts. Let's pop the password into an environment variable...
And change the command to use that. This time we want that shell expansion to happen.
echo -e "*2\r\n\$4\r\nAUTH\r\n\$16\r\n$REDISAUTH\r\n*1\r\n\$4\r\nINFO\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030 | tail -n +3
Now the command is sharable without giving away your password. There's one last thing to do for this example. That
INFO data is quite a lot to work through and we only really, say, want the
STATS section. That's not a problem, we just need to add that to the
INFO command, first by bumping the string count at the start of the command to 2 and then appending
\$5\r\nSTATS\r\n to the end.
$ echo -e "*2\r\n\$4\r\nAUTH\r\n\$16\r\n$REDISAUTH\r\n*2\r\n\$4\r\nINFO\r\n\$5\r\nSTATS\r\n" | nc sl-eu-lon-2-portal.1.dblayer.com 10030 | tail -n +3 # Stats total_connections_received:1700495 total_commands_processed:40375802 instantaneous_ops_per_sec:7 total_net_input_bytes:1984826397 total_net_output_bytes:2497942423646 instantaneous_input_kbps:0.41 instantaneous_output_kbps:1.10 rejected_connections:0 sync_full:5 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 evicted_keys:0 keyspace_hits:194 keyspace_misses:6 pubsub_channels:1 pubsub_patterns:0 latest_fork_usec:469 migrate_cached_sockets:0 $
Now we just have our statistics. And it's still one shell command.
What this gets us
You'll note that the Redis RESP protocol is remarkably simple. You can find out more about it on the RESP specification page. There are some other response types (
- for an error, which we saw when we got the NOAUTH message and
: for integers) and some other rules to take note of but it's also pretty simple to code for.
If you have a new language on your hands and no Redis driver, it is good to know that the protocol is so simple and readily implementable in even the most constrained of languages. As long as you can open a TCP socket to a port and read/write to it, you are good to go.
This should also help explain the types of Redis drivers that are around. The minimalist drivers basically provide enough to make sending commands to and receiving data from Redis; the user of the driver sends the strings for the commands.
Also, it's got its uses in the Internet of Things. In a future article, we'll be looking at that when we add Redis stats gathering (among other things) to a very resource-constrained device. Until then, have fun going low with Redis.
If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at firstname.lastname@example.org. We're happy to hear from you.