Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check whether socket is closed in bash?

I've got a file descriptor that points to a socket (example code below).

exec 3<>/dev/tcp/localhost/9999
echo -e "Some Command\n" >&3

Sometimes that socket closes and needs to be re-opened (a restart of the server).

How can I test if the socket (fd #3 in this case) is writable?

The echo will always succeed, regardless of whether the socket has been closed already or not.

like image 201
David Parks Avatar asked Jul 06 '11 09:07

David Parks


People also ask

How do you check if a socket has closed?

The most obvious way to accomplish this is having that process call read on the socket for a connection and check whether read returns 0 (i.e. reads zero bytes from the socket), in which case we know that the connection has been closed.


3 Answers

Solution is the feedback from the server.

When you send a request to the server, it needs to answer to it.

exec 3<>/dev/tcp/localhost/9999
echo -e "Some Command\n" >&3
sleep 5 # example max time given to server to respond
cat <&3 #receive an answer
check is correct, restart server otherwise

EDIT: using netcat to determine is the port is open

netcat -w 3 -z www.google.com 80
if[ $? -eq 0 ]
then
    echo port open
else
    echo port closed
fi
like image 162
bbaja42 Avatar answered Oct 12 '22 18:10

bbaja42


It has been awhile since op posted this so they might not see this but it might help someone else.

Anyway I was looking into this very issue and I found the following.

The open fd's (file descriptors) of a process are listed under /proc//fd.

exec 3<>/dev/tcp/localhost/9999

#check if still connected
if [ $(ls /proc/$$/fd | grep -w "3") == 3 ]; then
  #send data 
  echo -e "Some Command\n" >&3  
else
  #perform reconnect
  exec 3<>/dev/tcp/localhost/9999
fi

This wasn't tested but should be mostly ok. Might be some improvements as well. Also there is a window where the fd goes away between your check and the writing to fd. However that goes for all solutions so far.

like image 41
BenAnderson Avatar answered Oct 12 '22 17:10

BenAnderson


I will add my own final solution (in terse psudo-code):

{ while true; 
  read file; 
  write to STDOUT } | 
{ while true; 
  netcat command; 
  write STDIN to buffer when/if netcat exits; 
  loop to restart netcat & first process buffered data if exists; }

This separates the output of data (the reading of a file) and the processing of the data (sending it to a socket or buffering to a file when no socket is available). It uses the pipe to provide a temporary buffer when network issues occur.

The STDIN of the second code block buffers the output from the first codeblock. If netcat is unable to process data on stdin it will opt to write that out to a buffer file and try to re-start netcat. This way you don't have any period of time between checking that socket is open (something that's still tricky) and the actual write (which might still fail after checking that it's open).

like image 32
David Parks Avatar answered Oct 12 '22 18:10

David Parks