lsof -i: Find What Is Holding a Port
lsof -i:PORT lists the process holding a TCP/UDP port, including its PID and command name.
When a test server fails to bind because a leftover process from a prior step still owns the port, lsof -i names the culprit so you can kill it.
What it does
lsof lists open files, and on Unix a socket is a file. lsof -i filters to network connections; -i:8080 narrows to one port; -nP disables DNS and port-name lookups so output is fast and shows raw numbers. The COMMAND and PID columns tell you what to kill.
Common usage
lsof -i:8080 -nP
lsof -iTCP -sTCP:LISTEN -nP # all listening TCP sockets
lsof -i:5432 # who has Postgres’ port
# kill whatever holds the port
kill -9 "$(lsof -ti:8080)"Options
| Flag | What it does |
|---|---|
| -i[:port] | Show network files, optionally one port |
| -iTCP -sTCP:LISTEN | Only listening TCP sockets |
| -n | Do not resolve hostnames (faster) |
| -P | Do not resolve port numbers to names |
| -t | Terse: print PIDs only (for piping to kill) |
| -p <pid> | Restrict to one process |
In CI
The classic "bind: address already in use" failure means a previous step left a server running. lsof -ti:PORT | xargs -r kill -9 clears it before retrying. Pair -nP so a slow or absent DNS resolver on the runner does not stall the command.
Common errors in CI
lsof printing nothing for a port that is clearly in use often means the holder runs as another user; add sudo. "lsof: command not found" on slim images means the package is not installed; ss -ltnp is the lighter alternative. A "WARNING: can’t stat() ... file system" line is harmless and goes to stderr.