Efficiently test if a port is open on Linux?

LinuxBashShellPort

Linux Problem Overview


From a bash script how can I quickly find out whether a port 445 is open/listening on a server.

I have tried a couple of options, but I want something quick:

  1. lsof -i :445 (Takes seconds)
  2. netstat -an |grep 445 |grep LISTEN (Takes seconds)
  3. telnet (it doesn't return)
  4. nmap, netcat are not available on the server

It will be nice to know of a way that doesn't enumerate first and greps after that.

Linux Solutions


Solution 1 - 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.

Solution 2 - Linux

There's a very short with "fast answer" here : https://stackoverflow.com/questions/4922943/how-to-test-if-remote-tcp-port-is-opened-from-shell-script">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.

Solution 3 - Linux

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.

Solution 4 - Linux

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.

Solution 5 - Linux

Based on Spencer Rathbun's answer, using bash:

true &>/dev/null </dev/tcp/127.0.0.1/$PORT && echo open || echo closed

Solution 6 - Linux

they're listed in /proc/net/tcp.

it's the second column, after the ":", in hex:

> cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
   0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 10863 1 ffff88020c785400 99 0 0 10 -1                     
   1: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 7983 1 ffff88020eb7b3c0 99 0 0 10 -1                      
   2: 0500010A:948F 0900010A:2328 01 00000000:00000000 02:00000576 00000000  1000        0 10562454 2 ffff88010040f7c0 22 3 30 5 3                   
   3: 0500010A:E077 5F2F7D4A:0050 01 00000000:00000000 02:00000176 00000000  1000        0 10701021 2 ffff880100474080 41 3 22 10 -1                 
   4: 0500010A:8773 16EC97D1:0050 01 00000000:00000000 02:00000BDC 00000000  1000        0 10700849 2 ffff880104335440 57 3 18 10 -1                 
   5: 0500010A:8772 16EC97D1:0050 01 00000000:00000000 02:00000BF5 00000000  1000        0 10698952 2 ffff88010040e440 46 3 0 10 -1                  
   6: 0500010A:DD2C 0900010A:0016 01 00000000:00000000 02:0006E764 00000000  1000        0 9562907 2 ffff880104334740 22 3 30 5 4                    
   7: 0500010A:AAA4 6A717D4A:0050 08 00000000:00000001 02:00000929 00000000  1000        0 10696677 2 ffff880106cc77c0 45 3 0 10 -1  

so i guess one of those :50 in the third column must be stackoverflow :o)

look in man 5 proc for more details. and picking that apart with sed etc is left as an exercise for the gentle reader...

Solution 7 - Linux

ss -tl4 '( sport = :22 )'

2ms is quick enough ?

Add the colon and this works on Linux

Solution 8 - Linux

nc -l 8000

Where 8000 is the port number. If the port is free, it will start a server that you can close easily. If it isn't it will throw an error:

nc: Address already in use

Solution 9 - Linux

Here's one that works for both Mac and Linux:

netstat -aln | awk '$6 == "LISTEN" && $4 ~ "[\\.\:]445$"'

Solution 10 - Linux

I wanted to check if a port is open on one of our linux test servers. I was able to do that by trying to connect with telnet from my dev machine to the test server. On you dev machine try to run:

$ telnet test2.host.com 8080
Trying 05.066.137.184...
Connected to test2.host.com

In this example I want to check if port 8080 is open on host test2.host.com

Solution 11 - Linux

You can use netcat command as well

[location of netcat]/netcat -zv [ip] [port]

or

nc -zv [ip] [port]

-z – sets nc to simply scan for listening daemons, without actually sending any data to them.
-v – enables verbose mode.

Solution 12 - Linux

tcping is a great tool with a very low overhead.It also has a timeout argument to make it quicker:

[root@centos_f831dfb3 ~]# tcping 10.86.151.175 22 -t 1
10.86.151.175 port 22 open.
[root@centos_f831dfb3 ~]# tcping 10.86.150.194 22 -t 1
10.86.150.194 port 22 user timeout.
[root@centos_f831dfb3 ~]# tcping 1.1.1.1 22 -t 1
1.1.1.1 port 22 closed.

Solution 13 - Linux

nmap is the right tool. Simply use nmap example.com -p 80

You can use it from local or remote server. It also helps you identify if a firewall is blocking the access.

Solution 14 - Linux

If you're using iptables try:

iptables -nL

or

iptables -nL | grep 445

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAman JainView Question on Stackoverflow
Solution 1 - LinuxSpencer RathbunView Answer on Stackoverflow
Solution 2 - Linuxuser2187128View Answer on Stackoverflow
Solution 3 - LinuxanubhavaView Answer on Stackoverflow
Solution 4 - LinuxTonyView Answer on Stackoverflow
Solution 5 - Linuxuser1338062View Answer on Stackoverflow
Solution 6 - Linuxandrew cookeView Answer on Stackoverflow
Solution 7 - LinuxleucosView Answer on Stackoverflow
Solution 8 - LinuxJose EnriqueView Answer on Stackoverflow
Solution 9 - LinuxArtur BoderaView Answer on Stackoverflow
Solution 10 - LinuxrazvangView Answer on Stackoverflow
Solution 11 - LinuxSaurabhView Answer on Stackoverflow
Solution 12 - LinuxPayamView Answer on Stackoverflow
Solution 13 - LinuxzainengineerView Answer on Stackoverflow
Solution 14 - LinuxNozView Answer on Stackoverflow