Efficiently test if a port is open on Linux?

A surprise I found out recently is that Bash natively supports tcp connections as file descriptors. To use:

exec 6<>/dev/tcp/ip.addr.of.server/445
echo -e "GET / HTTP/1.0\n" >&6
cat <&6

I'm using 6 as the file descriptor because 0,1,2 are stdin, stdout, and stderr. 5 is sometimes used by Bash for child processes, so 3,4,6,7,8, and 9 should be safe.

As per the comment below, to test for listening on a local server in a script:

exec 6<>/dev/tcp/127.0.0.1/445 || echo "No one is listening!"
exec 6>&- # close output connection
exec 6<&- # close input connection

To determine if someone is listening, attempt to connect by loopback. If it fails, then the port is closed or we aren't allowed access. Afterwards, close the connection.

Modify this for your use case, such as sending an email, exiting the script on failure, or starting the required service.


There's a very short with "fast answer" here : How to test if remote TCP port is opened from Shell script?

nc -z <host> <port>; echo $?

I use it with 127.0.0.1 as "remote" address.

this returns "0" if the port is open and "1" if the port is closed

e.g.

nc -z 127.0.0.1 80; echo $?

-z Specifies that nc should just scan for listening daemons, without sending any data to them. It is an error to use this option in conjunc- tion with the -l option.


You can use netstat this way for much faster results:

On Linux:

netstat -lnt | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

On Mac:

netstat -anp tcp | awk '$6 == "LISTEN" && $4 ~ /\.445$/'

This will output a list of processes listening on the port (445 in this example) or it will output nothing if the port is free.


You can use netcat for this.

nc ip port < /dev/null

connects to the server and directly closes the connection again. If netcat is not able to connect, it returns a non-zero exit code. The exit code is stored in the variable $?. As an example,

nc ip port < /dev/null; echo $?

will return 0 if and only if netcat could successfully connect to the port.