Test if remote TCP port is open from a shell script Test if remote TCP port is open from a shell script shell shell

Test if remote TCP port is open from a shell script


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>


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 knownbash: /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.


TOC:

  • Using bash and timeout
    • Command
    • Examples
  • Using nc
    • Command
    • RHEL 6 (nc-1.84)
      • Installation
      • Examples
    • RHEL 7 (nmap-ncat-6.40)
      • Installation
      • Examples
  • Remarks

Using bash and timeout:

Note that timeout should be present with RHEL 6+, or is alternatively found in GNU coreutils 8.22. On MacOS, install it using brew install coreutils and use it as gtimeout.

Command:

$ timeout $TIMEOUT_SECONDS bash -c "</dev/tcp/${HOST}/${PORT}"; echo $?

If parametrizing the host and port, be sure to specify them as ${HOST} and ${PORT} as is above. Do not specify them merely as $HOST and $PORT, i.e. without the braces; it won't work in this case.

Example:

Success:

$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/80"; echo $?0

Failure:

$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?124

If you must preserve the exit status of bash,

$ timeout --preserve-status 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?143

Using nc:

Note that a backward incompatible version of nc gets installed on RHEL 7.

Command:

Note that the command below is unique in that it is identical for both RHEL 6 and 7. It's just the installation and output that are different.

$ nc -w $TIMEOUT_SECONDS -v $HOST $PORT </dev/null; echo $?

RHEL 6 (nc-1.84):

Installation:

$ sudo yum install nc

Examples:

Success:
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?Connection to canyouseeme.org 80 port [tcp/http] succeeded!0
Failure:
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?nc: connect to canyouseeme.org port 81 (tcp) timed out: Operation now in progress1

If the hostname maps to multiple IPs, the above failing command will cycle through many or all of them. For example:

$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progressnc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progressnc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progressnc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progressnc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress1

RHEL 7 (nmap-ncat-6.40):

Installation:

$ sudo yum install nmap-ncat

Examples:

Success:
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?Ncat: Version 6.40 ( http://nmap.org/ncat )Ncat: Connected to 52.202.215.126:80.Ncat: 0 bytes sent, 0 bytes received in 0.22 seconds.0
Failure:
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?Ncat: Version 6.40 ( http://nmap.org/ncat )Ncat: Connection timed out.1

If the hostname maps to multiple IPs, the above failing command will cycle through many or all of them. For example:

$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?Ncat: Version 6.40 ( http://nmap.org/ncat )Ncat: Connection to 104.43.195.251 failed: Connection timed out.Ncat: Trying next address...Ncat: Connection to 23.100.122.175 failed: Connection timed out.Ncat: Trying next address...Ncat: Connection to 23.96.52.53 failed: Connection timed out.Ncat: Trying next address...Ncat: Connection to 191.239.213.197 failed: Connection timed out.Ncat: Trying next address...Ncat: Connection timed out.1

Remarks:

The -v (--verbose) argument and the echo $? command are of course for illustration only.