How to find which process is using a port on Linux (ss, lsof, fuser)
Three commands that show the process holding a port on Linux, how to kill it safely with fuser -k 8080/tcp, and how to stop it grabbing the port again.
By The Opservo team
You're trying to start your app and it crashes immediately — 'Address already in use.' Or a new service won't bind because something is already sitting on port 8080. Either way, you need to know what's holding that port before you can fix anything. This happens constantly on shared servers and development machines, and the answer is usually one command away.
The fastest way: ss
The ss command (socket statistics) is the modern replacement for netstat and ships with virtually every Linux distribution. To find what's listening on a specific port — say, 8080 — run:
- sudo ss -tlnp sport = :8080
- # -t = TCP, -l = listening, -n = numeric ports, -p = show process
The output will show you the process name and PID directly in the last column, something like users:(("node",pid=14321,fd=22)). That tells you the process name is 'node', its PID is 14321, and it has the socket open on file descriptor 22. For UDP ports, swap -t for -u. To see all listening ports at once, drop the sport filter: sudo ss -tlnp
Using lsof for more detail
lsof (list open files) gives you richer context — especially useful when you want to trace back to a specific binary path or see all ports a process has open. To check port 5432 (the default PostgreSQL port):
- sudo lsof -i :5432
- sudo lsof -i TCP:5432 -s TCP:LISTEN # only LISTEN state
The output includes the command name, PID, user, file descriptor, and the full address binding. If multiple processes share the same port (rare but possible with SO_REUSEPORT), lsof will list all of them. You can also reverse the query — find every port a known PID has open with: sudo lsof -p 14321 -i
Quick check with fuser
If you just want the PID and nothing else, fuser is the most concise option:
- sudo fuser 8080/tcp
- sudo fuser 8080/tcp 8443/tcp # check multiple ports at once
fuser prints only the PID. Pair it with ps to get the full process details: sudo ps -p $(sudo fuser 8080/tcp 2>/dev/null) -o pid,user,cmd. This is handy in scripts where you want to kill a stubborn process cleanly before restarting a service.
What to do once you identify the process
Once you have the PID, you have a few options depending on the situation:
- It's a known service you accidentally started twice — stop it cleanly: sudo systemctl stop <service-name>
- It's a zombie or orphaned process — kill it: sudo kill -9 <pid>
- It's something unexpected — investigate before killing. Check the binary path with: ls -l /proc/<pid>/exe and see its full command line with: cat /proc/<pid>/cmdline | tr '\0' ' '
- It's a legitimate service that just started on the wrong port — check its config in /etc/systemd/system/ or wherever the service stores its port binding.
Never blindly kill a process owning a port. On a production server, that process might be a database or a queue broker whose abrupt termination causes data loss or cascading failures.
Checking all listening ports on the server
If you're doing a broader audit — new server, post-incident review, or just trying to understand what's actually running — pull the full picture with:
- sudo ss -tlnp # all listening TCP
- sudo ss -ulnp # all listening UDP
- sudo ss -tlnp | grep -v '127.0.0.1' # only externally accessible ports
Cross-reference this against your firewall rules (sudo ufw status or sudo iptables -L -n) to confirm you're not accidentally exposing something to the internet. It's a fast five-minute check that catches a surprising number of misconfigured services — things like Redis defaulting to 0.0.0.0:6379 with no authentication.
Making this less manual over time
Running these commands reactively works fine, but on a busy server you end up doing it repeatedly — every time a deploy fails, every time a service won't start, every time something looks slow. Opservo watches your server continuously and surfaces exactly this kind of information automatically: which processes are binding ports, when something new appears, and whether a port conflict is the reason a service just went unhealthy. That context shows up in plain English rather than requiring you to remember the right ss flags at 2 a.m.
For now, the short version: reach for ss first — it's fast and available everywhere. Use lsof when you need more context. Use fuser in scripts. And always check what a process actually is before you kill it.