Bash: TCP/Internet connection handling

There’re many problems nowadays, which could easier be solved through the internet. In this post I descripe how to address these problems by bash alone.

The standard way to connect to a server in the internet, is to embed the connection stream

exec 3<>/dev/tcp/$server/$ircPort || echo "Some text or doing, if connecting failed"

So for example if you want to get the first page of this blog, you might run

exec 3<>/dev/tcp/techoverflow.net/80 && echo -e "GET /index.html HTTP/1.1\r\nhost: techoverflow.net\r\nConnection: close\r\n\r\n" >&3 && cat <&3

However still more complex connections can be build, like this little irc bot

#! /bin/bash

# Here you might do some configs
nickname="testBot"
server="chat.freenode.net"
ircPort=6667
channels=(\#ubuntu) # You might add multiple channels to join like this:
# (channel1 channel2 channel3), however ensures that you escape each #
logFile=log.log

# do connection and joining stuff
echo "Connecting to server ..."
exec 3<>/dev/tcp/$server/$ircPort || echo "Connection failure! ..."
echo -ne "NICK ${nickname}\r\n" >&3
echo -ne "USER ${nickname} localhost localhost :simple irc bash bot\r\n" >&3
echo "Connect to all channels ..."
for ind in ${!channels[*]}
do
  echo -ne "JOIN ${channels[$ind]}\r\n" >&3
done

# program main loop
while true
do
  # read the next line from the connection
  line=$(head -n 1 <&3)
  # check, if (stream) connection closed (network error or something like that)
  # Note, that IRC Server never send empty lines
  if [ "$line" == "" ] || [ "$(ls /proc/$$/fd | grep -w '3')" != "3" ]
  then
    echo "Connection to irc server was closed! Quitting ..."
    break
  fi
  # output on screen (Note, that the \n was removed by the head command)
  echo "Reciving ..."
  printf "%s\n" "$line" | hd
  # reply PONG to PING else the IRC Server assumes that you're not listening
  # anymore and will kick you
  if [ "${line:0:5}" == "PING " ]
  then
    echo -n "PONG ${line:5}" >&3
    echo -ne "\r\n" >&3
  fi
  # Here more interaction stuff can be applied
  echo $line >> $logFile
done

exec 3>&- # close output connection
exec 3<&- # close input connection