So Something Is On Your Port and You Need To Know What It Is

You run a service. It won't start because the port is already in use. This happens more often than people care to admit, usually when you are stacking containers, running a second instance of something that should not be running, or dealing with a system that has been running long enough for forgotten processes to accumulate. Here is how you find the process, fix it, and ideally not pull your hair out doing it.

Uncovering Port Bandits Check Whats Using A Port In Linux Like A Pro

The first command almost everyone reaches for is netstat. It works. It has been around since the early days of Unix and it still shows up in most tutorials. The problem is netstat is deprecated on modern Linux systems and may not be installed by default on minimal containers or fresh server installs. You can still use it if it is available: The flags do this: -t for TCP, -l for listening only, -n for numeric addresses, -p for the process owning the socket. The output gives you the PID and program name in the last column. Clean enough. The real pro move these days is ss, which stands for sockets. It is part of iproute2, which ships on basically every modern distro now. It is faster than netstat because it reads directly from proc and sysfs rather than parsing /proc/*/net files like netstat does. In practice, on a busy server with thousands of connections, ss can return results in milliseconds where netstat might take a few seconds.

ss -tlnp | grep :8080

This will give you output like this: You get the process name, PID, and file descriptor count in one line. That fd number matters more than you might think, which I will get to later. If you want even more detail without piping through grep, try ss -tlnp with no filter. It dumps everything, but you can see at a glance what is listening across all ports. Useful when you are trying to figure out what a newly deployed service actually bound to instead of the port you told it to use.

Get the Full Details

4 Ways to Check Which Process is Using a Port in Linux
4 Ways to Check Which Process is Using a Port in Linux

Sometimes the process shows up but it is a container runtime or a proxy wrapper, not the actual application you are looking for. A lot of people hit this when using Docker or Podman. The PID in ss output might belong to dockerd or a conmon process. To dig deeper in those cases, use lsof:

lsof -i :8080

lsof lists open file descriptors. Since sockets are files in Unix, it gives you a very complete picture. The output includes the USER, command, PID, FD field showing the descriptor number, TYPE, NAME, and sometimes additional info. The FD column with something like 18u means file descriptor 18 opened for reading and writing. The u means read-write. r would be read-only, w write-only. I ran into a situation a while back where ss showed a process using a port but the PID pointed to a systemd service that had been masked. The service was not actually running the binary I expected. lsof revealed that the process had inherited the socket from a parent during a fork and the child process was the one that actually held the bind. kill -9 on the child released the port immediately, but the parent kept respawning it every thirty seconds. I had to mask the parent service with systemctl mask and then do a restart of the unit to fully free the port. That took about ten minutes of tracing that would have been two minutes if I had known to check the parent right away. Another thing people miss is that ss and netstat only show TCP and UDP by default in their common flag combinations. If you are troubleshooting a Unix domain socket situation, you need the -x flag:

ss -xlnp | grep mysocket.sock

And if you are on an older system where ss is not available, there is always reading from /proc directly. It is ugly but it works everywhere: The local_address column uses hexadecimal. Port 8080 is 1F90 in hex. You can convert with printf if you want, but it is easier to just use ss and not deal with manual conversions. For killing the offending process once you find it, be careful with -9. It works, but it does not give the process a chance to clean up connections, flush logs, or release temporary files. A normal SIGTERM first is better practice:

6 ways to Check a remote port status in Linux - howtouselinux
6 ways to Check a remote port status in Linux - howtouselinux
kill 4821

If that does not work within a reasonable time, then escalate to kill -9 4821. In my experience, about 90% of port conflicts resolve with a clean SIGTERM. The stubborn 10% are usually daemons with broken signal handlers or something running inside a container that does not propagate signals correctly. One practical tip that saves time: combine ss with awk to extract just the PID and command. This is something I run regularly when I need to script this:

ss -tlnp | awk '/:8080/ {print $NF}'

It pulls the last field which contains the users array. You can then pipe that into cut or sed to extract just the PID if you want to build a small cleanup script. I have a few of these lying around in cron jobs for services that tend to leak ports after crashes. The main limitation of all these tools is that they only see what is visible to your user context. If you are not root or in the right capability set, ss and lsof will hide process names and sometimes PIDs behind asterisks. Run them with sudo when possible, or use the cap_sys_ptrace capability if you are in a container and cannot easily get root access. Without elevated privileges, you are mostly blind to other users' processes and the port information becomes incomplete. Also worth noting: if you are working inside a Docker container with network namespace isolation, the PID you see from ss inside the container is the container-internal PID, not the host PID. The actual process on the host might be on a different machine or in a different namespace entirely. Check with nsenter or inspect the network namespace directly if the PID does not match anything on the host. This tripped me up for about an hour on a production system once, staring at a PID that clearly existed in the container but had no corresponding process when I sshed into the host.

Keep a small mental checklist: ss first for speed and modern syntax, lsof when you need the fd detail or when dealing with containers, netstat only on legacy systems, and /proc/net/tcp as a last resort when nothing else is installed. The order matters because each tool has different visibility into different layers of the stack, and picking the wrong one at the wrong time just wastes minutes you do not have.

How to Check if TCP Port is Open, Closed or in Use on Linux?
How to Check if TCP Port is Open, Closed or in Use on Linux?