Network programming with bash

Posted by Fred C (W6BSD) on Jan 25 2011

When executing a command on a /dev/tcp/$host/$port pseudo-device, Bash opens a TCP connection to the associated socket.

Exemple using TCP

$ cat </dev/tcp/
54496 08-01-31 02:30:53 00 0 3 345.7 UTC(NIST) *

Exemple using UDP

$ exec 4<>/dev/udp/ # new file descriptor
$ echo -e "Networking with bash" >&4 && head -1 <&4
Networking with bash
$ exec 4>&-                       # closing file descriptor '4'

In this example I open a datagram UDP connection to my home server on the echo service port 7. The file descriptor is open in read/write mode.

An almost useful program

This is an example of a small stripped down version of wget (yes very stripped down) written in bash.

The line exec 6<>/dev/tcp/$1/80 opens a socket in read write mode. Since we are using HTTP protocol 1.1 we need to pass the host name in the header with the line Host: $1. Also by default HTTP version 1.1 keeps all the connections alive unless specified otherwise. The line Connection: close tells the http server to close the connection once the response has been sent. I we forget this line the script will stay connected until the server times out.


exec 6<>/dev/tcp/$1/80

echo -e "GET ${PATH} HTTP/1.1" >&6
echo -e "Host: $1\nConnection: close\n" >&6
echo "Reading: http://${1}${PATH}" >&2

#read and discard the header
while read <&6
    if [ -z "$LINE" ]; then

#read the page
while read <&6
    echo -n $REPLY >&1
# close the file descriptor
exec 6<&-

This program takes two arguments, the server name and the path to the file to download.

$ ./ '/search?q=bsd' > ~/result.html

There is one caveat though. The version of bash you are using needs to be compiled with the flag --enable-net-redirections. This code should work on Mac, *BSD and most of the linux distributions (some Debian by default use a version of bash without net redirection).