Find and kill processes hogging your ports
Because "port 3000 already in use" is rage-inducing.
# Install
pip install psutil
# Use
python portkiller.py 3000 --forceYou're trying to start your dev server. Node says port 3000 is already in use. You forgot what's running. You have to Google "how to find process using port" for the 47th time. You run some arcane lsof command you copy-pasted. You find the PID. You kill it. Five minutes wasted.
Port Killer does this in one command.
# Clone the repository
git clone https://github.com/YOUR-USERNAME/portkiller.git
cd portkiller
# Install dependencies
pip install -r requirements.txt
# Make it executable (optional)
chmod +x portkiller.py
# Test it
python portkiller.py 9999# Install dependency
pip install psutil
# Download portkiller.py
# Make it executable (optional)
chmod +x portkiller.pySee INSTALL.md for system-wide installation and troubleshooting.
python portkiller.py 3000Output:
π Checking port 3000...
π Found 1 process(es) using port 3000:
π’ node (PID: 12345) - LISTEN
π Kill this process? (y/n):
python portkiller.py 3000 --forceOutput:
π Checking port 3000...
π Found 1 process(es) using port 3000:
π’ node (PID: 12345) - LISTEN
β
Killed node (PID: 12345)
π Successfully freed port 3000
python portkiller.py 3000 --verboseOutput:
π Checking port 3000...
π Found 1 process(es) using port 3000:
π’ node (PID: 12345) - LISTEN
Local: 0.0.0.0:3000
Remote: N/A
python portkiller.py 8080Output:
π Checking port 8080...
β
Port 8080 is not in use
port- Port number to check (required)-f, --force- Kill without asking for confirmation-v, --verbose- Show detailed connection information
- Uses
psutilto scan all network connections - Finds processes listening on the specified port
- Gets process name and PID
- Kills the process (gracefully with SIGTERM, then SIGKILL if needed)
- Handles zombie processes correctly
Works on:
- β Linux
- β macOS
- β Windows
Uses Python's psutil library for cross-platform process management.
Problem: After killing a process, psutil.pid_exists() would still return True because the process became a zombie (dead but not yet reaped by parent).
Solution: Check both PID existence AND process status. Accept STATUS_ZOMBIE as a successful kill.
if not psutil.pid_exists(pid):
return True
# PID exists but might be zombie
p = psutil.Process(pid)
if p.status() == psutil.STATUS_ZOMBIE:
return True # It's dead, just waiting to be reapedProblem: In sandboxed environments or without proper permissions, psutil.net_connections() can't see all processes.
Solution: Catch AccessDenied exceptions and provide helpful error messages directing users to run with sudo/admin privileges.
Initial approach: Used lsof and netstat system commands.
Problem: Not available in all environments, different syntax across platforms.
Solution: Switched to psutil which handles cross-platform differences internally and works without system tools.
- Permissions: May need sudo/admin privileges to see or kill some processes
- Network namespace: Only sees connections in the current network namespace
- Port range: Only works with TCP/UDP ports (doesn't handle Unix sockets)
- Lines of code: 197
- Time to build: ~5 hours (including debugging zombie processes)
- Dependencies:
psutilonly - Tested on: Linux (Ubuntu 24)
Web Development:
python portkiller.py 3000 --force # React dev server
python portkiller.py 8000 --force # Django server
python portkiller.py 5000 --force # Flask serverDatabase Development:
python portkiller.py 5432 --force # PostgreSQL
python portkiller.py 3306 --force # MySQL
python portkiller.py 27017 --force # MongoDBBefore running tests:
# Kill any leftover test servers
python portkiller.py 8080 --force
npm run testManual way:
# Linux/Mac
lsof -ti:3000 | xargs kill -9
# Windows
netstat -ano | findstr :3000
taskkill /PID <pid> /FProblems with manual:
- Have to remember different commands for different OS
- Need to parse output yourself
- No confirmation or safety checks
- Easy to kill wrong process
Port Killer way:
python portkiller.py 3000Benefits:
- Works everywhere
- Shows you what you're killing
- Safe by default (confirmation required)
- Pretty output with emojis
- Handles multiple processes
- Graceful shutdown by default
Add an alias to your shell config:
# ~/.bashrc or ~/.zshrc
alias pk="python /path/to/portkiller.py"Then use it like:
pk 3000 -fOr make it a proper command:
sudo ln -s /path/to/portkiller.py /usr/local/bin/portkillerThen:
portkiller 3000 -fIf I were to continue this project:
- Multi-port support:
portkiller 3000,8000,8080 -f - Range support:
portkiller 3000-3010 -f - Process whitelist: Don't kill critical system processes
- History: Remember what ports you killed recently
- Auto-restart: Kill and restart the process
- Port scanner: Find all ports in use on the system
But for V1, it does exactly what it needs to: kill that damn process hogging your port.
MIT - Do whatever you want with it. See LICENSE for details.
Found a bug? Have an idea? Contributions welcome! See CONTRIBUTING.md for guidelines.
portkiller/
βββ portkiller.py # Main script
βββ README.md # You are here
βββ INSTALL.md # Installation guide
βββ CONTRIBUTING.md # Contribution guidelines
βββ LICENSE # MIT License
βββ requirements.txt # Python dependencies
βββ .gitignore # Git ignore rules
βββ examples/
β βββ usage_examples.sh # Quick reference
β βββ common_ports.md # Port reference guide
β βββ test_portkiller.py # Integration tests
βββ .github/
βββ workflows/
βββ ci.yml # GitHub Actions CI
Built as part of the "30 for 30" challenge - 30 useful tools in 30 days.
Day 5: Port Killer β