Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if remote TCP port is open from a shell script

I'm looking for a quick and simple method for properly testing if a given TCP port is open on a remote server, from inside a Shell script.

I've managed to do it with the telnet command, and it works fine when the port is opened, but it doesn't seem to timeout when it's not and just hangs there...

Here's a sample:

l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"` if [ "$?" -ne 0 ]; then   echo "Connection to $SERVER on port $PORT failed"   exit 1 else   echo "Connection to $SERVER on port $PORT succeeded"   exit 0 fi 

I either need a better way, or a way to force telnet to timeout if it doesn't connect in under 8 seconds for example, and return something I can catch in Shell (return code, or string in stdout).

I know of the Perl method, which uses the IO::Socket::INET module and wrote a successful script that tests a port, but would rather like to avoid using Perl if possible.

Note: This is what my server is running (where I need to run this from)

SunOS 5.10 Generic_139556-08 i86pc i386 i86pc

like image 779
Yanick Girouard Avatar asked Feb 07 '11 15:02

Yanick Girouard


People also ask

How can I tell if a remote port is open?

Enter "telnet + IP address or hostname + port number" (e.g., telnet www.example.com 1723 or telnet 10.17. xxx. xxx 5000) to run the telnet command in Command Prompt and test the TCP port status. If the port is open, only a cursor will show.


2 Answers

As pointed by B. Rhodes, nc (netcat) will do the job. A more compact way to use it:

nc -z <host> <port> 

That way nc will only check if the port is open, exiting with 0 on success, 1 on failure.

For a quick interactive check (with a 5 seconds timeout):

nc -z -v -w5 <host> <port> 
like image 148
Alessio Gaeta Avatar answered Oct 05 '22 17:10

Alessio Gaeta


It's easy enough to do with the -z and -w TIMEOUT options to nc, but not all systems have nc installed. If you have a recent enough version of bash, this will work:

# Connection successful: $ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/80' $ echo $? 0  # Connection failure prior to the timeout $ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/sfsfdfdff.com/80' bash: sfsfdfdff.com: Name or service not known bash: /dev/tcp/sfsfdfdff.com/80: Invalid argument $ echo $? 1  # Connection not established by the timeout $ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/81' $ echo $? 124 

What's happening here is that timeout will run the subcommand and kill it if it doesn't exit within the specified timeout (1 second in the above example). In this case bash is the subcommand and uses its special /dev/tcp handling to try and open a connection to the server and port specified. If bash can open the connection within the timeout, cat will just close it immediately (since it's reading from /dev/null) and exit with a status code of 0 which will propagate through bash and then timeout. If bash gets a connection failure prior to the specified timeout, then bash will exit with an exit code of 1 which timeout will also return. And if bash isn't able to establish a connection and the specified timeout expires, then timeout will kill bash and exit with a status of 124.

like image 27
onlynone Avatar answered Oct 05 '22 17:10

onlynone