Multi-platformtoolsTested on real hardware

Check what's using a port (Linux / macOS / Windows)

Find which process is listening on a given port number on Linux, macOS, or Windows. Essential for diagnosing port conflicts when a service fails to start.

Shellbash
Updated
Script
bash
# Replace 8080 with the port number you're investigating

# ── Linux ──��──────────────────────────────────────────────────────────────────
# ss (modern — preferred, no extra install needed)
sudo ss -tulnp | grep ':8080'

# lsof alternative
sudo lsof -i :8080

# ── macOS ─────────────────────────────────────────────────────────────────────
# sudo lsof -i :8080
# sudo lsof -i :8080 -n -P     # -n skips DNS lookups, -P shows port numbers

# ── Windows (PowerShell or Command Prompt — run as Administrator) ─────────────
# netstat -ano | findstr :8080
# Then look up the PID shown in the last column:
# tasklist /FI "PID eq 1234"
# To kill the process:
# Stop-Process -Id 1234 -Force

Why these commands

“Address already in use” is one of the most common errors when starting a self-hosted service, and it’s one of the most confusing without knowing how to diagnose it. The service you’re trying to start needs a specific port, but something else is already listening on that port — either a previous instance of the same service that didn’t shut down cleanly, a completely different process that happens to use the same port, or occasionally a service that reserved the port at system startup before your Docker container could claim it.

The socket statistics tools (ss on Linux, lsof on macOS) show you exactly what’s listening on any port and which process owns it — process ID, process name, and the specific socket binding. With that information, you can either stop the conflicting process, move your service to a different port, or identify that you’re dealing with a zombie of your own service that needs to be killed.

The commands differ per OS because socket inspection is implemented at the kernel level, and each OS exposes it differently. Linux’s ss (socket statistics) is the modern replacement for netstat, built-in to every current distribution, and faster because it reads socket state directly from the kernel without a library. macOS uses lsof (list open files — network sockets are files in Unix). Windows uses netstat plus tasklist to correlate PIDs to process names, since Windows networking predates the Unix convention of sockets as files.

When to use this

Run this when:

  • A service fails to start with address already in use or bind: permission denied
  • You want to confirm a service is actually listening before debugging connectivity
  • You need to identify and stop a process occupying a port before starting your own service

Linux

sudo ss -tulnp | grep ':8080'

Flag breakdown:

  • -t TCP, -u UDP
  • -l listening sockets only
  • -n show port numbers (skip DNS/service name lookup)
  • -p show the process name and PID

Example output:

tcp  LISTEN  0  128  0.0.0.0:8080  0.0.0.0:*  users:(("nginx",pid=1234,fd=6))

To show all listening ports (no filter):

sudo ss -tulnp

lsof — list open files

sudo lsof -i :8080

Find the process name from a PID

ps -p 1234 -o comm=
# or
cat /proc/1234/cmdline | tr '\0' ' '

Kill the process on a port

sudo kill "$(sudo ss -tulnp | grep ':8080' | awk '{print $7}' | grep -oP 'pid=\K[0-9]+')"
# or more safely, get the PID first and verify before killing:
sudo ss -tulnp | grep ':8080'
sudo kill 1234

macOS

sudo lsof -i :8080

Add -n -P to skip slow DNS lookups and show raw port numbers:

sudo lsof -i :8080 -n -P

Example output:

COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
ruby     5678   josh   10u  IPv4  0x...      0t0  TCP *:8080 (LISTEN)

Kill the process:

sudo kill 5678
# or force-kill if it doesn't respond:
sudo kill -9 5678

Show all listening ports on macOS

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

Windows

Open PowerShell or Command Prompt (Administrator):

netstat -ano | findstr :8080

Example output:

TCP    0.0.0.0:8080    0.0.0.0:0    LISTENING    4512

The last column is the PID. Look up the process name:

tasklist /FI "PID eq 4512"

Kill the process:

Stop-Process -Id 4512 -Force

Show all listening ports on Windows

netstat -ano | findstr LISTENING

Or in PowerShell for a cleaner view:

Get-NetTCPConnection -State Listen | Sort-Object LocalPort | Select-Object LocalPort, OwningProcess, @{n='Process';e={(Get-Process -Id $_.OwningProcess).Name}}

Notes

  • On Linux, ss replaces the older netstat command (net-tools package) — ss is faster and always available without installing extra packages
  • Ports below 1024 require root on Linux/macOS — a service binding to port 80 or 443 must run as root, use authbind, or sit behind a reverse proxy
  • On Windows, netstat -b shows the executable name directly but requires Administrator and is slow — tasklist /FI "PID eq ..." after netstat -ano is faster