Mar 242011
 

Being able to communicate over the network directly with bash is nothing new, but it’s not something that is used very often, nor is it something that most bash tutorials teach you about.  Most of the time, it is probably easier and faster to call other commands like netcat, mutt, or wget (just a few off the top of my head that I use quite often) rather than using built-ins, but I’ve run into a few cases in the past where one or more of these tools was not available on a production machine and installing them would have taken too long by the time I went through the red tape of getting approval through standard change control procedures.

One of the fringe benefits of this write-up is that we also get to review a highly overlooked and underused aspect of bash programming – file descriptors!

First thing we need to do is open a connection to a remote host.  In bash, this is accomplished by redirecting input and/or output to a special file in /dev.  The file path will vary depending on the remote host and port to which you want to connect, but for our purposes, let’s use our good friend Google to demonstrate how to do a pseudo wget or curl.  The first thing we’ll do is

The exec 5<> portion tells bash to open a file descriptor numbered 5 (an arbitrary number I picked) and use it to read data from and write data to the pseudo-device located at /dev/tcp/www.google.com/80 (which, if you run ls in /dev, you’ll find does not really exist).  All this says is to connect to www.google.com on TCP port 80 – the standard HTTP port.

Despite the fact that /dev/tcp/www.google.com/80 does not exist, you’ll find that there is a new file created located at /dev/fd/5 that is a symbolic link to something along the lines of “socket:[<some number>].”  So far, so good.

So now we’ve got a file descriptor communicating over the network.  Let’s send an HTTP request:

You can verify the request went through okay by verifying that the return code was 0:

We can get the response that Google’s web server sent us with the following:

You should see a bunch of HTML and javascript get blasted to your terminal, so maybe you’d want to write it to a file instead (note that running the initial cat <&5 flushes the data buffer and you’d have to do another GET request before running the following):

Using this method you could use a shell script to check simple web pages or script a mail session by connecting directly to your mail relay, or do any number of network testing.  It’s no replacement for the binary tools that are created to do the job, but in a pinch, these tips could really come in handy.