Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What's the easiest way to find an unused local port?

Currently I'm using something similar to this:


while [ "$quit" -ne 1 ]; do
  netstat -a | grep $port >> /dev/null
  if [ $? -gt 0 ]; then
    port=`expr $port + 1`

It feels awfully roundabout, so I'm wondering if there's a more simple path such as a builtin that I've missed.

share|improve this question
Why do you want to do that? It's inherently racy (and inefficient - and least add -n to netstat and a more selective grep). The way to do it is to try and open a port in whatever mode you need, and try another one if it's not available. – Mat Nov 16 '12 at 16:04
@Mat I'm trying to automatically find an open port to use with ssh -D as a SOCKS server. – mybuddymichael Nov 16 '12 at 16:08
up vote 9 down vote accepted

The script in your answer has a race condition, the only way to avoid it is to atomically check if it is open by trying to open it. If the port is in use, the program should quit with a failure to open the port.

For example, say you're trying to listen with netcat.

read lowerPort upperPort < /proc/sys/net/ipv4/ip_local_port_range
while :; do
    for (( port = lowerPort ; port <= upperPort ; port++ )); do
        nc -l -p "$port" 2>/dev/null && break 2
share|improve this answer
This races badly when multiple applications employ this trick. Mark's answer is much better as it is randomized. – Lekensteyn Nov 2 '14 at 22:29
@Lekensteyn: Where do you see a race condition here? – Chris Down Nov 2 '14 at 23:23
This port tries to use the first port available. When you have two concurrent processes, then the port which just got checked might be reused. Re-reading your answer, it seems that you suggest to retry binding on an available port until all ports are exhausted. Assuming that the program in question can distinguish between "port in use" and other errors, it should be fine (though randomization would still make it better for unpredictability). – Lekensteyn Nov 2 '14 at 23:44
@Lekensteyn Successful port binding results in the kernel returning EADDRINUSE if you try and use it again, it's not possible that "the port which just got checked might be reused". – Chris Down Nov 3 '14 at 0:56
Yes, I wrongly assumed that you would exit the loop and use $port in the actual program as in while ...; done; program --port $port. – Lekensteyn Nov 3 '14 at 9:11

My solution is to bind to port 0, which asks the kernel to allocate a port from it's ip_local_port_range. Then, close the socket and use that port number in your configuration.

This works because the kernel doesn't seem to reuse port numbers until it absolutely has to. Subsequent binds to port 0 will allocate a different port number. Python code:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 0))
addr = s.getsockname()
print addr[1]

This gives just a number of a port, eg. 60123.

Run this program 10 000 times (you should run these concurrently), and you'll get 10 000 different port numbers. Therefore, I think it's pretty safe to use the ports.

share|improve this answer
Here is a one-liner (valid with Python 2 and Python 3): python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()' – Lekensteyn Nov 2 '14 at 22:28
I ran the mentioned experiment, and not all results were unique. My histogram was: { 1: 7006, 2: 1249, 3: 151, 4: 8, 5: 1, 6: 1} – bukzor Jan 31 '15 at 2:00
Is there an easy way to add in a check that the port is not blocked by a firewall, or rather only searches open ports? – Mark Lakata Mar 12 '15 at 20:25
I ran the script 10,000 times and got similar results to @bukzor: 1282 ports used twice, 153 used 3 times, 10 used 4 times and 1 used 5 times. – dshepherd Feb 17 at 13:08

This is part of a function I have in my .bashrc, which dynamically creates SSH tunnels and tries to use any port in a range:

   lps=( 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 )

   # find a free listening port
   for port in ${lps[@]}; do
      lsof -i -n -P |grep LISTEN |grep -q ":${port}"
      [ $? -eq 1 ] && { lp=$port; break; }
   [ "$lp" = "null" ] && { echo "no free local ports available"; return 2; }
   return $port


share|improve this answer

On Linux, you could do something like:

ss -tln | 
  awk 'NR > 1{gsub(/.*:/,"",$4); print $4}' |
  sort -un |
  awk -v n=1080 '$0 < n {next}; $0 == n {n++; next}; {exit}; END {print n}'

To find the first free port above 1080. Note that ss -D would bind on the loopback interface, so in theory you could reuse port 1080 if a socket has it bound on another address. Another way would be to actually try and bind it:

perl -MSocket -le 'socket S, PF_INET, SOCK_STREAM,getprotobyname("tcp");
  $port = 1080;
  ++$port until bind S, sockaddr_in($port,inet_aton("127.1"));
  print $port'
share|improve this answer
This does, however, involve a race condition between attempting to open the port and actually using it. – Chris Down Nov 17 '12 at 0:02
@ChrisDown, Indeed, but with ssh -D, I can't see any better option. The -O forward option of ssh doesn't return an error when the forward fail. – Stéphane Chazelas Nov 17 '12 at 9:00
read LOWERPORT UPPERPORT < /proc/sys/net/ipv4/ip_local_port_range
while :
        PORT="`shuf -i $LOWERPORT-$UPPERPORT -n 1`"
        ss -lpn | grep -q ":$PORT " || break
echo $PORT

Credits to Chris Down

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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