1

Typically an easy diagnostic approach to checking an application server is running is to run telnet again the host and port:

telnet somehost port

The issue is that some operating systems, such as macOS now make the tool unavailable by default. For this reason, instead of trying to see how to install telnet, I am curious to know if there are any other CLI approaches to check a server is listening, without needing special privileges?

Just to clarify I am looking for solutions that are as quick to use on any system as telnet, which is achievable in 5 seconds. Coding a solution doesn’t really offer a quick access approach.

4

You can try several ways to check if something listen on particular port:

With wget/curl

wget your_IP:port

With netstat

netstat -an|grep LISTEN|grep :port

With lsof

lsof -i :port

With netcat

nc -vz your_IP port

With /proc filesystem (probably will work only on linux) (explained here)

With ss

ss|grep LISTEN|grep :port

With nmap

nmap -sS -O -pport your_IP

EDIT1 Also (almost) every ssh,http,ftp client can be used, but sometime will be hard to understand if port is closed by firewall or not available.
EDIT2 Found in this Q/A sample way to use cat and echo to do the job:

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

or with only exec command (if you do not see error port is open):

exec 6<>/dev/tcp/your_IP/port

And I found a way to use only awk to do the job (original here):

awk -v port=your_port 'function hextodec(str,ret,n,i,k,c){
    ret = 0
    n = length(str)
    for (i = 1; i <= n; i++) {
        c = tolower(substr(str, i, 1))
        k = index("123456789abcdef", c)
        ret = ret * 16 + k
    }
    return ret
}
function getIP(str,ret){
    ret=hextodec(substr(str,index(str,":")-2,2)); 
    for (i=5; i>0; i-=2) {
        ret = ret"."hextodec(substr(str,i,2))
    }
    ret = ret":"hextodec(substr(str,index(str,":")+1,4))
    return ret
} 
NR > 1 {{local=getIP($2);remote=getIP($3) }{ if (remote ~ "0:0" && local ~ ":"port) print local}}' /proc/net/tcp 

EDIT3 As mentioned in to comment some of the methods, especially based on /dev filesystem may bot work in your environment

  • you should mention explictily that /dev/tcp/host/port only works in bash (and gawk) and that it's something internal, completely fake (you cannot use that path with external commands). – mosvy Feb 10 at 11:45
  • @mosvy, by fake, do you mean is local? – Romeo Ninov Feb 10 at 13:55
  • no, I mean that it's completely internal to bash, only bash and its builtin commands are able to use those paths. compare cat </dev/tcp/localhost/smtp to cat /dev/tcp/localhost/smtp – mosvy Feb 10 at 14:37
  • @mosvy, I added comment in to the answer :) – Romeo Ninov Feb 10 at 14:47
2

It's actually better not to use the telnet tool, which does more than just open a TCP socket, in certain circumstances trying to speak the TELNET protocol over the opened connection. There are many tools that can be used to open a TCP socket, not least the client tools of all of the other TCP-based protocols, like FTP clients. Again, like telnet, these can end up trying to speak their respective protocols after the connection opens.

For this very basic operation of making a TCP connection and immediately closing it, without attempting to speak any protocol over the connection, one does best to look at low-level tools. nc is one, which I leave to other answers. But others are the various UCSPI-TCP and UCSPI-SSL clients, whose job is solely to do exactly what you want: open the connection. Just make the program that they then chain-load to do nothing except report the success.

  • tcp-socket-connect in the nosh package:
    tcp-socket-connect "${HOST}" "${PORT}" \
         sh -c 'echo Connected to ${TCPREMOTEIP}:${TCPREMOTEPORT} successfully.'
    This does both IPv4 and IPv6.
  • the tcpclient in the djbwares package, a slightly polished version of Daniel J. Bernstein's original tcpclient:
    tcpclient -H -R -l 0 "${HOST}" "${PORT}" \
         sh -c 'echo Connected to ${TCPREMOTEIP}:${TCPREMOTEPORT} successfully.'
    This only does IPv4, although a few patched versions exist that can also do IPv6.
  • Laurent Bercot's s6-tcpclient from s6-networking:
    s6-tcpclient -N -H -R -l 0 "${HOST}" "${PORT}" \
         sh -c 'echo Connected to ${TCPREMOTEIP}:${TCPREMOTEPORT} successfully.'
    This does both IPv4 and IPv6.
  • William Baxter's sslclient:
    sslclient -H -R -l 0 "${HOST}" "${PORT}" \
         sh -c 'echo Connected to ${SSLREMOTEIP}:${SSLREMOTEPORT} successfully.'
    This negotiates SSL/TLS as well. It only does IPv4, although Felix von Leitner publishes a patched version that does IPv6 too.

See the manual pages for details. The options used here turn off various informational lookups about the endpoints that you do not need for a connectivity test. The input host and port can be symbolic. What is printed will be numeric.

These tools are portable, and can be built from source on a range of systems. Indeed they are even pre-built and packaged as binaries for several operating systems, or available through ports, including but not limited to:

  • My concern here is that these solutions aren’t a 5 second check with a command line tool, which is the beauty of telnet. – Andre M Feb 10 at 23:01
  • Clearly that is not the beauty of telnet, as telnet needs to be compiled/installed first on your system, as stated in the question. Then there's the well-known fact that telnet speaks an actual protocol as pointed out. Giving these commands a host and port, the only two inputs that they take and much the same as one would give telnet, is a "5 second" job, furthermore. – JdeBP Feb 11 at 5:37
1

To solve this problem, I wrote a perl script:

#!/usr/bin/perl -w

# tries to connect to the given IP and port (tcp)

use strict;
use IO::Socket;

my $desthost = shift or die "Usage: $0 host port\n";
my $destport = shift or die "Usage: $0 host port\n";

gethostbyname($desthost) || die "Invalid host given\n";

my $handle = IO::Socket::INET->new(
        PeerAddr => $desthost,
        PeerPort => $destport,
        Proto    => 'tcp')
    or die "can't connect to $desthost:$destport: $!\n";
close $handle;
print "Success!\n"

It simulates a telnet connection (see the hard-coded 'tcp') and allows you to enter a hostname and port; it reports back success or failure based on the remote side answering (listening) at that port.

  • Coding a solution isn’t practical and doesn’t really offer a quick solution. The key is really to be able to use something readily available with the minimum effort. – Andre M Feb 10 at 23:02
  • It looks like it could become a one-liner quite easily. – Thorbjørn Ravn Andersen Feb 11 at 0:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.