DEV Community

Amaresh Pelleti
Amaresh Pelleti

Posted on Originally published at devtoolhub.com

Find What's Using a Port on Linux: lsof, ss, and ps in One Workflow

Originally published on DevToolHub.

"Address already in use" tells you a port is taken. It doesn't tell you by what. Finding the actual process bound to a port on Linux is a three-command workflow, not one magic incantation — and two of those three commands have a syntax gotcha that produces wrong or misleading output if you get it backwards.

Step 1: Confirm the port is actually bound, with ss

ss -tlnp is the fastest way to see what's listening. -t restricts output to TCP sockets, -l shows only listening sockets, -n skips reverse-DNS lookups so it returns instantly, and -p shows the owning process — in practice you need sudo to see details for other users' processes.

ss -tlnp | grep :8080
LISTEN 0  128  0.0.0.0:8080  0.0.0.0:*  users:(("node",pid=48213,fd=22))
Enter fullscreen mode Exit fullscreen mode

That already gives you the PID and process name. ss only covers network sockets, though — it won't show a stale listener's other open file handles.

Step 2: Confirm the exact process, with lsof

lsof -i :8080 answers the same question from the file-descriptor side. lsof's -i accepts [46][protocol][@hostname|hostaddr][:service|port], so -i :8080 means any protocol/host on port 8080, while -i tcp:8080 narrows to TCP only.

lsof -i :8080
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node    48213 deploy   22u  IPv4 812933      0t0  TCP *:8080 (LISTEN)
Enter fullscreen mode Exit fullscreen mode

The FD column matters if you're also chasing a "too many open files" error — lsof shows every open file and socket for that PID.

Step 3: Inspect the process before you kill it

ps -p 48213 -o pid,ppid,user,cmd,%cpu,%mem
Enter fullscreen mode Exit fullscreen mode

The gotcha: ps aux and ps -aux are not the same command. Per the ps man page, ps -aux under POSIX rules means "processes with a terminal plus processes owned by a user named x," and it only behaves like ps aux because ps falls back to that when no user x exists. Stick to ps aux for the traditional listing, and ps -p PID -o ... once you have a specific PID.

If you're hunting the heaviest process by resource use instead, ps aux --sort=-%cpu | head sorts descending by CPU — and per the man page, %cpu "will not add up to 100% unless you are lucky," since it's a lifetime ratio, not a live snapshot like top produces.

Killing it safely

kill -15 48213
Enter fullscreen mode Exit fullscreen mode

-15 sends SIGTERM, a clean-shutdown request. Only escalate to kill -9 48213 (SIGKILL) if the process is still alive a few seconds later — SIGKILL skips cleanup and can leave sockets or lock files behind.

Quick Summary:

  • ss -tlnp | grep :PORT finds the PID fastest, with -n avoiding slow DNS lookups
  • lsof -i :PORT cross-checks from the file-descriptor side and shows every open file for that PID
  • ps -aux means "processes owned by user x" under POSIX and only falls back to ps aux — type ps aux without the dash
  • %cpu is a lifetime ratio and won't sum to 100% across processes
  • Send SIGTERM (kill -15) before SIGKILL (kill -9)

Full workflow at DevToolHub.

Top comments (0)