Server--:--:--You--:--:--

Finding What Is Using a Port on Linux

By Prabath Thalangama· September 16, 2026· 3 min read
#linux#networking#troubleshooting

Introduction

bind: address already in use — something already holds the port you want. The fix is one command; the trick is knowing which, and handling the cases where the obvious command comes up empty (containers, TIME_WAIT, namespaces).

The commands

ss — the modern default

# Every listening TCP/UDP socket, with the owning process
sudo ss -tulpn

# Just port 8080
sudo ss -tulpn 'sport = :8080'

# Who is CONNECTED to port 5432 right now (not just listening)
sudo ss -tnp 'dport = :5432 or sport = :5432'

Flags: t TCP, u UDP, l listening, p process, n numeric (don't resolve names — much faster). The users:(("nginx",pid=1234,fd=6)) field is your answer.

lsof — file-descriptor view

sudo lsof -i :8080
sudo lsof -iTCP -sTCP:LISTEN -P -n

lsof also shows which address it's bound to (127.0.0.1:8080 vs *:8080) and the file descriptor number, which is handy when a process has the port open but on a socket it forgot to close.

fuser — quick and blunt

sudo fuser 8080/tcp            # prints the PID(s)
sudo fuser -k 8080/tcp         # ...and kills them (careful)

The cases that come up empty

It's a container

ss on the host shows docker-proxy or nothing useful. The real listener is in the container's namespace:

docker ps --filter publish=8080
docker inspect --format '{{.State.Pid}}' <container>
sudo nsenter -t <pid> -n ss -tulpn      # run ss inside the container's netns

Or just docker port <container>.

It's in a network namespace (not a container)

ip netns list
sudo ip netns exec <ns> ss -tulpn

The port is in TIME_WAIT, not held by anything

After a server closes a connection, the socket sits in TIME_WAIT for ~60 s. ss -tan state time-wait shows them. A new server can't bind unless it sets SO_REUSEADDR — most do (net.ipv4.tcp_tw_reuse is for outbound). If your app doesn't, it just has to wait, or you fix the app to set the socket option.

It's a raw/PF_PACKET socket

tcpdump, DHCP clients, and some VPNs use packet sockets that ss -tulpn doesn't list. sudo ss -0 -p or sudo lsof -i more broadly.

systemd socket activation

The socket is held by systemd itself, not the service (the service starts on first connection). systemctl list-sockets and look for a .socket unit on that port.

Verification and troubleshooting

# After killing, confirm it's actually free
sudo ss -tulpn | grep ':8080' || echo "port is free"

# Bind is failing but ss shows nothing — check the exact address
sudo ss -tulpn | grep 8080
# app wants 0.0.0.0:8080 but something holds 127.0.0.1:8080 (or ::)
  • ss shows nothing, bind still fails — it's a namespace/container, an IPv6 vs IPv4 mismatch (::8080 blocks 0.0.0.0:8080 when net.ipv6.bindv6only=0), or you're not root and the owning process belongs to someone else — sudo.
  • Killed the process, port still busy for a minuteTIME_WAIT from its open connections. Normal; wait or use SO_REUSEADDR.
  • Process keeps coming back — it's under systemd/supervisor with Restart=. Stop the unit, not the PID.
  • fuser -k killed too muchfuser kills every process with that port open, including clients. Prefer ss -tulpnkill <specific pid>.
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.