Linux command get unused port

20

6

I'm looking for a command or script which returns an unused port on my ubuntu linux system. I have look on internet and the only thing I find is about the used/Listen port with the nestat command. Apparently something with the netstat command will work but don't know what exactly. Any idea how?

Thanks.

user2429082

Posted 2015-03-04T12:39:14.453

Reputation: 329

possible duplicate of How can I check which ports are busy and which ports are free on my Linux machine?

– duDE – 2015-03-04T12:43:24.053

1

Why do you need to do that exactly? If you are developing a server, you can bind to port 0 and the OS will allocate a free port for you, you have nothing to search. Otherwise searching and then binding is prone to race conditions. See for example https://stackoverflow.com/questions/1365265/on-localhost-how-do-i-pick-a-free-port-number or https://stackoverflow.com/questions/1075399/how-to-bind-to-any-available-port

– Patrick Mevzek – 2018-02-10T17:57:40.047

Answers

14

netstat -lat gives the complete list of listening and established ports.

When a port is not on any of those states doesn't exist for the system, so you won't find a command that shows the list of unused ports.

Keep in mind that there are 65535 ports, so anything that isn't on netstat -lat is an unused port.

The following bash script will do a simple scan of tcp ports, and let you know which are open and which are closed :

#!/bin/bash
IP=$1
first_port=$2
last_port=$3
function scanner

{
for ((port=$first_port; port<=$last_port; port++))
        do
                (echo >/dev/tcp/$IP/$port)> /dev/null 2>&1 && echo $port open || echo "$port closed"
        done
}

scanner

If you save it as portscan.sh then it must be run as ./portscan.sh IP first_port last_port, for example: ./portscan 127.0.0.1 20 135 will scan the local equipment from ports 20 to 135

jcbermu

Posted 2015-03-04T12:39:14.453

Reputation: 15 868

7

Ruby 2.x (one-liner):

ruby -e 'require "socket"; puts Addrinfo.tcp("", 0).bind {|s| s.local_address.ip_port }'

On my machine right now that printed:

42644

A subsequent invocation printed:

36168

This technique causes the current user to request an unused port (bind to port "0"), and then prints out the port number that the operating system provided. And since the current user is the one asking, ports below 1024 will not be returned (unless current user = root).

Credit where credit's due - this solution comes from a comment by Franklin Yu on unix.stackexchange.com's What's the easiest way to find an unused local port?

G. Sylvie Davies

Posted 2015-03-04T12:39:14.453

Reputation: 171

How could I assign the result of this to a variable in a bash script? – Neil Stevens – 2017-12-15T12:42:28.717

export PORT=$(ruby -e 'require "socket"; puts Addrinfo.tcp("", 0).bind {|s| s.local_address.ip_port }') – G. Sylvie Davies – 2017-12-16T05:52:23.913

3

Short bash script that randomly generates a number between 1025 and 60000 and loops until that number isn't found in the list of used ports. This is a quick 'n dirty solution that has a bias to larger ports:

CHECK="do while"

while [[ ! -z $CHECK ]]; do
    PORT=$(( ( RANDOM % 60000 )  + 1025 ))
    CHECK=$(sudo netstat -ap | grep $PORT)
done

echo $PORT

Taras

Posted 2015-03-04T12:39:14.453

Reputation: 31

Check your grep command, see comment on adarshr answer – Nick – 2017-02-10T16:10:39.947

2

One-liner

I've put together a nice one-liner that quickly serves the purpose, allowing to grab an arbitrary number of ports in an arbitrary range (here it's divided in 4 lines for readability):

comm -23 \
<(seq "$FROM" "$TO") \
<(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep '[0-9]\{1,5\}' | sort -n | uniq) \
| shuf | head -n "$HOWMANY"

Line by line

comm is a utility that compares sorted lines in two files. It outputs three columns: lines that appear only in the first file, lines that only appear in the second one and common lines. By specifying -23 we suppress the latter columns and only keep the first one. We can use this to obtain the difference of two sets, expressed as a sequence of text lines. I learned about comm here.

The first file is the range of ports that we can select from. seq produces a sorted sequence of numbers from $FROM to $TO. The result is piped to comm as the first file using process substitution.

The second file is the sorted list of ports, that we obtain by calling the ss command (with -t meaning TCP ports, -a meaning all - established and listening - and -n numeric - don't try to resolve, say, 22 to ssh). We then pick only the fourth column with awk, which contains the local address and port. We use cut to split address and port with the : delimiter and keep only the latter (-f2). ss also output an header, that we get rid of by grepping for non-empty sequences of numbers that are no longer than 5. We then comply with comm's requirement by sorting numerically (-n) and getting rid of duplicates with uniq.

Now we have a sorted list of open ports, that we can shuffle to then grab the first "$HOWMANY" ones with head -n.

Example

Grab the three random open ports in the private range (49152-65535)

comm -23 <(seq 49152 65535) <(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep "[0-9]\{1,5\}" | sort | uniq) | shuf | head -n 3

could return for example

54930
57937
51399

Notes

  • switch -t with -u in ss to get free UDP ports instead.
  • drop shuf if you're not interested in grabbing a random port

stefanobaghino

Posted 2015-03-04T12:39:14.453

Reputation: 129

1

I like your one-liner, this version properly parse IPv6 e.g. [::1]:52792 and use --no-header option instead of grep. https://gist.github.com/fstefanov/ff4dcec7ded59514421bf944d1bb9a6f

– Filip Stefanov – 2018-07-14T02:19:27.933

1

I needed to find just a single random unused port and not print a list of them. Here's my bash solution.

#/bin/bash

function random_unused_port {
    local port=$(shuf -i 2000-65000 -n 1)
    netstat -lat | grep $port > /dev/null
    if [[ $? == 1 ]] ; then
        export RANDOM_PORT=$port
    else
        random_unused_port
    fi
}

random_unused_port

And use it by sourcing it

$ . ./random_unused_port.sh; echo $RANDOM_PORT

adarshr

Posted 2015-03-04T12:39:14.453

Reputation: 131

I like the idea here, however your grep command will not return what you intend. The good thing is it will be conservative, but if the next random port is 2000, and port 2000 is open, but port 20000 is in use, it will keep looking, so the outcome will be not the full range of available ports. – Nick – 2017-02-10T16:10:05.543

1

Maybe another solution based on the list of used ports:

function random_unused_port {
   (netstat --listening --all --tcp --numeric | 
    sed '1,2d; s/[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*:\([0-9]*\)[[:space:]]*.*/\1/g' |
    sort -n | uniq; seq 1 1000; seq 1 65535
    ) | sort -n | uniq -u | shuf -n 1
}

RANDOM_PORT=$(random_unused_port)

The netstat command generates a list of all open ports. The sed command extracts the port numbers, which are in use and the sort/uniq construct returns a uniq list of open ports. Second step is to generate a list of port numbers starting at 1 and finishing at 1000 (reserved ports) and an additional list of all port numbers starting at 1 up to 65535. The final list contains all available ports only once and the uniq -u will extract them. Last, the shuf -n 1 will pick one random port out of the complete list of available ports. Nevertheless, there will be a race condition, before one is able to reserve the port.

Frank Förster

Posted 2015-03-04T12:39:14.453

Reputation: 111

1

I needed to find the next open port starting from a port number; here is my attempt using @Taras' solution.

_check="placeholder"
START_FROM=1900
PORT=$(( ( "$RANDOM" % 1000 ) + $START_FROM ))
while [[ ! -z "${_check}" ]]; do
    ((PORT++))
    _check=$(ss -tulpn | grep ":${PORT}")
done

Alberto Chiusole

Posted 2015-03-04T12:39:14.453

Reputation: 111

0

If 54321 is your port, run:

sudo netstat -ap |grep 54321

Some variations of using netstat can be found here.

Overmind

Posted 2015-03-04T12:39:14.453

Reputation: 8 562

This command will only show me if the port 54321 is use or not. What I want is to find is unused port. – user2429082 – 2015-03-04T13:03:06.893

Unused is ambiguous. You want to check which port are available to listen to ? Or which port are available to connect to ? Any that aren't in use are available. As user, you may use the ones above 1024, as root, you may use also the ones under 1024. – Overmind – 2015-03-04T13:11:22.307