How to Free Up a TCP/IP Port on Linux, macOS, and Windows
TLDR: Find the process using the port with lsof -i :PORT (Linux/macOS) or netstat -ano | findstr :PORT (Windows), then kill it with kill PID or taskkill /PID pid. For persistent services, stop them properly with systemctl stop service or the Services manager. Always identify what's using the port before killing it to avoid disrupting important services.
When you try to start a server or application and see "address already in use" or "port already in use," something else is bound to that port. Here's how to find what's using it and free it up.
Linux: Find and Free Ports
Find What's Using the Port
The most straightforward tool is lsof (list open files):
# Find what's using port 8080
sudo lsof -i :8080
# Output:
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# node 12345 john 21u IPv4 98765 0t0 TCP *:8080 (LISTEN)
This tells you:
COMMAND: The program name (node)PID: Process ID (12345)USER: Who owns the process (john)- The port is in
LISTENstate
If you prefer ss (socket statistics):
# Find listening process on port 8080
sudo ss -tulpn | grep :8080
# Output:
# tcp LISTEN 0 128 *:8080 *:* users:(("node",pid=12345,fd=21))
Or use netstat (older but still available):
# Find listening process on port 8080
sudo netstat -tulpn | grep :8080
# Output:
# tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 12345/node
Kill the Process
Once you have the PID, you can kill the process:
# Gracefully terminate (allows cleanup)
kill 12345
# Force kill if it doesn't respond
kill -9 12345
# Or in one command if you're certain:
sudo lsof -ti :8080 | xargs kill -9
The -t flag tells lsof to output only PIDs, making it easy to pipe to kill.
Stop a System Service
If the port is used by a system service, use systemctl instead of killing:
# Check if it's a systemd service
systemctl status nginx
# Stop the service gracefully
sudo systemctl stop nginx
# Prevent it from starting on boot
sudo systemctl disable nginx
# Or stop and disable in one command
sudo systemctl disable --now nginx
Stopping via systemctl is cleaner than killing - it allows proper shutdown and cleanup.
Check for Services Running in Docker
If you're using Docker, the port might be occupied by a container:
# List containers using port mapping
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}"
# Output:
# CONTAINER ID NAMES PORTS
# a1b2c3d4e5f6 webapp 0.0.0.0:8080->80/tcp
# Stop the container
docker stop a1b2c3d4e5f6
# Or stop by name
docker stop webapp
macOS: Find and Free Ports
macOS uses the same tools as Linux:
Find What's Using the Port
# Find process using port 3000
lsof -i :3000
# Output:
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# node 56789 sarah 21u IPv4 0xabcdef123 0t0 TCP *:3000 (LISTEN)
You don't need sudo on macOS for lsof if you own the process.
Kill the Process
# Kill by PID
kill 56789
# Or force kill
kill -9 56789
# One-liner to kill whatever's on port 3000
lsof -ti :3000 | xargs kill -9
Stop macOS Services
For system services:
# List running services
launchctl list | grep -i apache
# Stop Apache (example)
sudo apachectl stop
# Or for other services
sudo launchctl unload /Library/LaunchDaemons/com.example.service.plist
Windows: Find and Free Ports
Windows uses different tools but the concept is the same.
Find What's Using the Port
REM Find process using port 8080
netstat -ano | findstr :8080
REM Output:
REM TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 5432
REM ^^^^
REM PID
The last column is the process ID (PID). To find out what program that is:
REM Get process details
tasklist /FI "PID eq 5432"
REM Output:
REM Image Name PID Session Name Session# Mem Usage
REM node.exe 5432 Console 1 45,678 K
Or use PowerShell for a cleaner view:
# Find what's using port 8080
Get-NetTCPConnection -LocalPort 8080 |
Select-Object LocalAddress, LocalPort, State, OwningProcess,
@{Name="ProcessName";Expression={(Get-Process -Id $_.OwningProcess).Name}}
# Output:
# LocalAddress LocalPort State OwningProcess ProcessName
# 0.0.0.0 8080 Listen 5432 node
Kill the Process
REM Kill process by PID
taskkill /PID 5432
REM Force kill if it doesn't respond
taskkill /PID 5432 /F
REM Kill by process name (kills all instances)
taskkill /IM node.exe /F
In PowerShell:
# Kill process by PID
Stop-Process -Id 5432
# Force kill
Stop-Process -Id 5432 -Force
# Kill all node processes
Stop-Process -Name node -Force
Stop Windows Services
For system services, use the Services manager or command line:
REM Stop a service
net stop "Apache2.4"
REM Or use sc (service control)
sc stop Apache2.4
In PowerShell:
# Stop a service
Stop-Service -Name "Apache2.4"
# Stop and disable
Stop-Service -Name "Apache2.4"
Set-Service -Name "Apache2.4" -StartupType Disabled
Or use the GUI:
- Press
Win+R, typeservices.msc, press Enter - Find the service in the list
- Right-click → Stop
Common Port Conflicts
Port 80/443 (HTTP/HTTPS)
Usually occupied by a web server:
# Linux/macOS
sudo lsof -i :80
sudo lsof -i :443
# Likely culprits: apache2, nginx, httpd
# Stop Apache
sudo systemctl stop apache2 # Ubuntu/Debian
sudo systemctl stop httpd # RHEL/CentOS
# Stop NGINX
sudo systemctl stop nginx
On Windows, check IIS:
REM Stop IIS
iisreset /stop
REM Or stop the service
net stop W3SVC
Port 3000 (Development Servers)
Often used by Node.js, React, Rails:
# Find and kill
lsof -ti :3000 | xargs kill -9
# Or on Windows
netstat -ano | findstr :3000
taskkill /PID <pid> /F
Port 5432 (PostgreSQL)
# Linux
sudo systemctl stop postgresql
# macOS (Homebrew)
brew services stop postgresql
# Windows
net stop postgresql-x64-13
Port 3306 (MySQL)
# Linux
sudo systemctl stop mysql
# macOS
brew services stop mysql
# Windows
net stop MySQL80
Port 6379 (Redis)
# Linux
sudo systemctl stop redis
# macOS
brew services stop redis
# Windows
redis-cli shutdown
Preventing Port Conflicts
Configure Services to Use Different Ports
Instead of killing processes, change port configurations:
# NGINX - edit /etc/nginx/sites-available/default
server {
listen 8080; # Changed from 80
...
}
# Restart to apply
sudo systemctl restart nginx
For Node.js apps:
// Use environment variable for port
const PORT = process.env.PORT || 3000;
app.listen(PORT);
Then start with a different port:
PORT=3001 node app.js
Use Docker Port Mapping
Map container ports to different host ports:
# Map container port 80 to host port 8080
docker run -p 8080:80 nginx
# Multiple containers on different host ports
docker run -p 8080:80 nginx
docker run -p 8081:80 nginx
Check Ports Before Starting
#!/bin/bash
# start-server.sh - Check port before starting
PORT=8080
if lsof -Pi :$PORT -sTCP:LISTEN -t >/dev/null ; then
echo "Port $PORT is already in use"
echo "Process using port:"
lsof -i :$PORT
exit 1
else
echo "Port $PORT is available"
./start-my-server.sh --port $PORT
fi
When Ports Won't Free Up
Sometimes a port stays in TIME_WAIT state after you kill the process:
# Check port state
sudo ss -tan | grep :8080
# Output:
# TIME-WAIT 0 0 192.168.1.10:8080 192.168.1.100:54321
TIME_WAIT prevents immediate reuse of the port. Wait 30-120 seconds, or use SO_REUSEADDR in your application:
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))
This lets your application bind immediately after the previous instance closed.
Safety Checks Before Killing
Always verify what you're killing:
# Check process details
ps aux | grep 12345
# Check what files it has open
lsof -p 12345
# Check command line arguments
cat /proc/12345/cmdline | tr '\0' ' '
Don't kill processes unless you know what they are:
- System services might cause issues if killed
- Databases could corrupt data if not shut down properly
- Other users' processes aren't yours to kill (on shared systems)
Automating Port Cleanup
For development, create a helper script:
#!/bin/bash
# free-port.sh - Free up a port
PORT=$1
if [ -z "$PORT" ]; then
echo "Usage: $0 <port>"
exit 1
fi
echo "Finding process using port $PORT..."
PID=$(lsof -ti :$PORT)
if [ -z "$PID" ]; then
echo "No process is using port $PORT"
exit 0
fi
echo "Port $PORT is used by PID $PID"
ps -p $PID -o comm=
read -p "Kill this process? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
kill $PID
echo "Process killed"
else
echo "Cancelled"
fi
Usage:
chmod +x free-port.sh
./free-port.sh 8080
The key to freeing up a port is identifying what's using it first, then deciding the appropriate action - stopping a service cleanly, killing a hung process, or reconfiguring to use a different port. Always verify what you're stopping to avoid breaking production services or other users' work.
Found an issue?