Find and kill processes using a specific port on Linux

Beginner 15 min Oct 19, 2026
Ubuntu 24.04 Ubuntu 22.04 Debian 12 Debian 11 AlmaLinux 9 Rocky Linux 9 Fedora 41

Learn how to find which process is using a specific port on Linux, identify its owner safely, and kill it with the right tool. Covers lsof, ss, fuser, and how to prevent address already in use errors for good.

Prerequisites

  • A Linux server or VM with sudo access
  • Basic familiarity with the terminal

What this solves

When you start a service or app and see Error: listen EADDRINUSE: address already in use :::3000 or bind: Address already in use, it means another process already has that port open. This tutorial shows how to find exactly which process holds a port, confirm it is safe to kill, and stop it cleanly without resorting to a server reboot.

This applies to any TCP or UDP port conflict: web servers fighting over port 80, a stuck Node.js process holding 3000, or a zombie database process blocking 5432. If you are dealing with Postgres specifically refusing new connections rather than a port conflict, see fix PostgreSQL FATAL sorry, too many clients already instead.

Step-by-step configuration

Understand why address already in use happens

Every listening socket binds to an IP address and port combination. The kernel will not let two processes bind to the same port on the same interface at the same time, so if an old process did not shut down properly, or a previous instance is still running, your new process fails to start.

This commonly happens after a crashed process, a container that did not release its port, or a developer running the same app twice in different terminals.

Install lsof and net-tools if missing

lsof and ss are the two main tools you need. ss ships by default on nearly every modern distro via iproute2, but lsof sometimes needs installing.

sudo apt update
sudo apt install -y lsof
sudo dnf install -y lsof

Find the process using lsof

The -i flag filters by network connection. Replace 3000 with whatever port is blocked.

sudo lsof -i :3000

Typical output looks like this:

COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node    18234   deploy   22u  IPv4 184028      0t0  TCP *:3000 (LISTEN)

The second column is the PID you will need to kill the process. The USER column tells you which account owns it.

Find the process using ss

ss is faster than lsof on busy systems and is the modern replacement for netstat. Use it when you need a quick overview or when lsof is not installed.

sudo ss -ltnp | grep ':3000'

Flags explained: -l shows listening sockets only, -t filters to TCP, -n shows numeric ports instead of resolving service names, -p shows the owning process.

For UDP services such as DNS resolvers or syslog listeners, swap -t for -u.

sudo ss -lunp | grep ':53'

Identify the process owner and PID safely

Before killing anything, confirm what the process actually is. Killing the wrong PID can take down an unrelated service, a database, or even an SSH session if port numbers happen to collide.

ps -fp 18234

This shows the full command line, parent process, and the user that launched it. If the owner is a system account like postgres or www-data, stopping it with kill directly can leave the service in an inconsistent state. In that case prefer the service's own stop command, for example sudo systemctl stop postgresql, over killing the PID manually.

Note: If the process is owned by root or a system user different from yours, you need sudo to inspect or kill it. Never blindly sudo-kill PIDs you have not identified with ps first.

Kill the process with kill

Once you have confirmed the PID is safe to terminate, send a graceful termination signal first.

kill -15 18234

-15 is SIGTERM, which asks the process to shut down cleanly, closing file handles and finishing in-flight requests. Wait a few seconds and check it is gone.

ps -p 18234

If the process ignores SIGTERM and is still running, escalate to SIGKILL, which forces an immediate stop with no cleanup.

kill -9 18234
Warning: SIGKILL does not let the process flush buffers, close database connections, or release locks. Only use it after SIGTERM has failed, and never on a database process without checking its own shutdown procedure first.

Kill by name with pkill

When multiple processes share a name, for example several stale node workers, killing by PID one at a time is slow. pkill matches by process name or command line pattern.

pkill -15 -f 'node server.js'

The -f flag matches against the full command line rather than just the process name, which avoids accidentally killing unrelated processes that happen to be named node.

Always do a dry run first with pgrep to see what would be matched before you kill anything.

pgrep -fa 'node server.js'

Kill by port directly with fuser

fuser lets you kill whatever is bound to a port without looking up the PID manually. This is the fastest one-liner for a quick fix in development.

sudo fuser -k 3000/tcp

This sends SIGKILL by default to every process using that port. For a graceful shutdown, send SIGTERM explicitly instead.

sudo fuser -k -TERM 3000/tcp
Warning: fuser -k kills every process attached to that port, including ones you may not have intended to stop. Run sudo fuser -v 3000/tcp first to see what is actually listening before killing.

Prevent conflicts with SO_REUSEADDR

A common cause of repeated address already in use errors is a socket stuck in TIME_WAIT after a restart. Most frameworks and languages let you enable SO_REUSEADDR so the OS allows immediate rebinding to a port in that state.

In Node.js with the built-in net or http module, this is handled automatically on most Linux distributions. For custom C or Python socket servers, set it explicitly before binding.

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', 8080))
sock.listen(5)

This does not bypass a genuinely active listener. It only allows rebinding to a socket that is winding down in TIME_WAIT, which is the state you see most often right after a restart.

Prevent conflicts with systemd socket activation

For services managed by systemd, socket activation lets systemd own the listening socket and hand it to your application on demand. This avoids race conditions where two instances of your app try to bind the same port during a restart.

[Unit]
Description=Socket for myapp

[Socket]
ListenStream=8080

[Install]
WantedBy=sockets.target
[Unit]
Description=My application
Requires=myapp.socket

[Service]
User=myapp
ExecStart=/usr/local/bin/myapp
Restart=on-failure

[Install]
WantedBy=multi-user.target

Enable the socket unit, not the service directly. systemd will start the service automatically the first time a connection arrives on the socket.

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.socket

If you run multiple backend instances behind a reverse proxy, you may also want to look at configuring systemd user services for application startup to manage per-user app instances cleanly.

Check listening ports on startup

Add a quick habit of checking what is already listening before you start a new service, especially on shared development boxes.

sudo ss -ltnp

For a persistent audit trail, you can also script a check that runs at boot and logs all listening ports to a file for later review.

sudo ss -ltnp > /var/log/listening-ports-$(date +%Y%m%d).log

If you want this automated on a schedule rather than a one-off check, configuring cron jobs and system task scheduling covers how to run checks like this reliably.

Verify your setup

After killing the process, confirm the port is actually free before starting your application again.

sudo ss -ltnp | grep ':3000'
sudo lsof -i :3000

Both commands should return no output if the port is clear. Then start your service and verify it binds successfully.

sudo systemctl status myapp
curl -I http://127.0.0.1:3000

Common issues

SymptomCauseFix
lsof shows nothing but port still fails to bindProcess is bound to IPv6 only, lsof filter missing protocolRun sudo lsof -i6:3000 and sudo lsof -i4:3000 separately
Permission denied when running lsof or ssProcess owned by another user or system accountPrefix the command with sudo to see root-owned sockets
kill -9 does not free the port immediatelySocket is in TIME_WAIT, not actually still bound by a live processWait 30-60 seconds, or enable SO_REUSEADDR in the app code
Port reopens right after killing the processA supervisor like systemd or PM2 auto-restarts itStop the service unit first: sudo systemctl stop myapp
fuser reports No process specifiedWrong protocol suffix usedConfirm TCP vs UDP, try sudo fuser -v 3000/tcp
Multiple PIDs returned for the same portForked worker processes sharing a listening socketKill the parent PID shown in ps -f --ppid, not individual workers

Next steps

Running this in production?

Want this handled for you? This works for a single server. When you run multiple environments or need services available 24/7 without port conflicts breaking deploys, keeping it healthy is a different job. See how we run infrastructure like this for European teams.
#linux #ports #lsof #networking #troubleshooting

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. Fully managed, with one fixed contact who knows your setup.

You get one fixed contact who knows your setup

At their desk in Rotterdam 13:07 · reachable in a message, no ticket form