Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding next open port

Is there any way, using basic Unix commands, to find the next unused port number, starting at port 4444 and going upwards? I'm ssh'ed (via openssh) into a Windows XP machine, running Cygwin tools and using a bash shell.

Thanks, - Dave

like image 226
Dave Avatar asked Aug 04 '11 13:08

Dave


3 Answers

Try this:

for port in $(seq 4444 65000); do echo -ne "\035" | telnet 127.0.0.1 $port > /dev/null 2>&1; [ $? -eq 1 ] && echo "unused $port" && break; done

where

seq 4444 65000 - port range for check
echo -ne "\035" - escape character to force close telnet session (^])

if telnet finishes with exit code 1 that mean connection refused:

$ telnet 127.0.0.1 4444
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
$ echo $?
1

else we decided that connection was success with exit code 0.

EDIT: Special for cygwin: You need to install additional package inetutils that is contain telnet port and use the script as follows:

for port in $(seq 4444 65000); do echo -ne "\035" | /usr/bin/telnet 127.0.0.1 $port > /dev/null 2>&1; [ $? -eq 1 ] && echo "unused $port" && break; done
like image 87
user478681 Avatar answered Nov 20 '22 11:11

user478681


Same as above, but written as a function

function get_unused_port() {
  for port in $(seq 4444 65000);
  do
    echo -ne "\035" | telnet 127.0.0.1 $port > /dev/null 2>&1;
    [ $? -eq 1 ] && echo "$port" && break;
  done
}
FREE_PORT="$(get_unused_port)"
echo $FREE_PORT
like image 26
Ben Haynor Avatar answered Nov 20 '22 10:11

Ben Haynor


The following function doesn't depend on telnet/netcat as it generates a random port in the local port range and compares it with a list of ports currently used by running applications.

Should work on any *nix that supports proc filesystem. Generates a free ephemeral port to be used by your application.

function EPHEMERAL_PORT(){
    while true; do 
        LISTENING_PORTS=$(cat /proc/net/tcp | awk 'NR >1 {print $2}' | awk -F':' '{print $2}');
        LISTENING_PORTS=$(for PORT in ${LISTENING_PORTS}; do echo $((16#${PORT})); done|sort -g);
        # echo "32768 60999" | read LPORT UPORT
        read LPORT UPORT < /proc/sys/net/ipv4/ip_local_port_range
        MPORT=$[$LPORT + ($RANDOM % $UPORT)];
        if (echo "${LISTENING_PORTS[@]}" | grep -xqv $MPORT); then
            echo $MPORT;
            break;
        fi
    done
}

Apparently TCP connections can be used as file descriptors on linux. The following function uses that technique and should be faster than the previous one.

function EPHYMERAL_PORT(){
    LPORT=32768;
    UPORT=60999;
    while true; do
        MPORT=$[$LPORT + ($RANDOM % $UPORT)];
        (echo "" >/dev/tcp/127.0.0.1/${MPORT}) >/dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo $MPORT;
            return 0;
        fi
    done
}

This is a cross platform function that uses osquery to get a list of listening ports. Should also work on Windows.

function EPHYMERAL_PORT(){
    while true; do 
        echo "32768 60999" | read LPORT UPORT
        MPORT=$[$LPORT + ($RANDOM % $UPORT)];
        LISTENING_PORTS=$(osqueryi --header=false --list "select port from listening_ports order by port");
        if (echo "${LISTENING_PORTS[@]}" | grep -xqv $MPORT); then
            echo $MPORT;
            break;
        fi
    done
}

Usage instructions. Bind the output to a variable and use in scripts. Tested on Ubuntu 16.04

root@ubuntu:~> EPHYMERAL_PORT
59453
root@ubuntu:~> PORT=$(EPHYMERAL_PORT)
like image 44
Sandeep Avatar answered Nov 20 '22 11:11

Sandeep