Commandkill

Kill the process using a port

Finds the process listening on a TCP port and stops it in one line, scoped to the listener so you don't kill the clients connected to it.

Last updated

Commandkill
kill $(lsof -t -i tcp:3000 -sTCP:LISTEN)

How it works

The two filters are the whole point. `-i tcp:3000` restricts the match to TCP, and `-sTCP:LISTEN` restricts it to the socket that is LISTENING on that port — the server itself. `-t` prints PIDs only, so $(...) feeds them straight to kill without you retyping anything.

Without those filters this command is genuinely dangerous. A bare `lsof -i:3000` matches any socket using port 3000 at either end — including every client currently connected to your dev server, which is typically your own browser. Piping that list into kill is how people SIGKILL their browser while trying to free a port.

Watch out for

  • →This sends SIGTERM, which lets the process close file handles and flush writes. Escalate to `kill -9` (SIGKILL) only when a normal kill doesn't land — SIGKILL cannot be caught, so nothing gets cleaned up.
  • →If multiple processes genuinely share the port (rare, but possible with SO_REUSEPORT), lsof returns several PIDs and all of them are signalled at once.
  • →This is Linux/macOS only — lsof and this kill syntax don't exist on native Windows. There, find the PID with netstat -ano | findstr :3000, then stop it with taskkill /PID <pid>.

Part by part

lsof -t
Terse output — process IDs only, with no header. That is what makes the result usable directly as an argument.
-i tcp:3000
Restrict to TCP port 3000. Naming the protocol as well as the port is what stops UDP sockets appearing in the list.
-sTCP:LISTEN
Only sockets in the LISTEN state. This is the load-bearing flag: without it the list includes every client connected to that port.
kill
Sends SIGTERM, which asks the process to shut down cleanly. Deliberately not kill -9.

Common mistakes

  • kill -9 $(lsof -t -i:3000)

    Two problems at once. Without -sTCP:LISTEN this matches every process with a connection to port 3000, which can include your own browser — so it force-kills the tab you were testing in. And -9 gives the server no chance to release the port or flush its work.

    kill $(lsof -t -i tcp:3000 -sTCP:LISTEN)
  • kill $(lsof -t -i tcp:3000)

    Better, but still matches established connections as well as the listener. On a machine where a browser tab is open against the port, that browser is in the list.

  • killall node

    Kills every node process on the machine, including editors, language servers and unrelated projects. It resolves the port conflict and creates several new problems.

Questions

What if the process ignores SIGTERM?

Then escalate to kill -9 deliberately, having seen that the polite signal did not work. SIGKILL cannot be caught, so nothing is flushed and no cleanup runs — it is a last resort rather than a starting point.

What is the equivalent on Windows?

netstat -ano | findstr :3000 gives the PID, then taskkill /PID <pid> /F. PowerShell has Get-NetTCPConnection -LocalPort 3000, which is easier to read and filter.

Why is the port still busy after the process exits?

Usually TIME_WAIT, where the kernel holds the socket briefly to catch stray packets. It clears in a minute or two; a server that sets SO_REUSEADDR can bind immediately regardless.

Is there a simpler command?

fuser -k 3000/tcp does it in one step on Linux, and npx kill-port 3000 is convenient in a Node project. Both are less precise than the lsof form about what exactly they are killing.

Related in Commands