How to find and kill processes listening to port 3000 on macOS
How do I manually find and kill processes using the terminal that listen to or use my TCP ports? I’m on macOS.
Sometimes, after a crash or bug, my Rails app gets locked to port 3000, and I can’t find it using ps -ef…
When running:
rails server
I get:
Address already in use - bind(2) (Errno::EADDRINUSE)
The same issue happens when stopping the Node.js process. Even after the process is stopped and the app stops running, port 3000 is locked. When starting the app again, I get:
Address already in use (Errno::EADDRINUSE)
To find and kill processes listening to port 3000 on macOS, you’ll need to use terminal commands to identify the process ID (PID) and then terminate it. The most effective approach is to first use lsof to list processes using the port, then use kill to terminate the specific process.
Contents
- Finding Processes on Port 3000
- Killing the Process
- Alternative Methods
- Preventing Future Issues
- Advanced Troubleshooting
Finding Processes on Port 3000
The lsof (list open files) command is the most reliable way to find processes using a specific port on macOS. Here are the essential commands:
Using lsof to Find the Process
sudo lsof -i :3000
This command will show you all processes listening on port 3000. The output will include:
- Process ID (PID)
- Process name
- User who owns the process
- Device and network information
Example output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rails 12345 user 20u IPv4 0x12345678 0t0 TCP localhost:3000 (LISTEN)
node 12346 user 21u IPv4 0x12345679 0t0 TCP localhost:3000 (LISTEN)
Alternative lsof Commands
If you need more detailed information:
sudo lsof -ti :3000 # Only shows PIDs
sudo lsof -i -P -n | grep 3000 # Shows port with IP addresses
Using netstat (Legacy Method)
For older macOS versions or alternative approaches:
sudo netstat -an | grep 3000
sudo netstat -anvp tcp | grep 3000
Killing the Process
Once you’ve identified the process ID, you can terminate it using several methods:
Graceful Termination (Recommended)
Start with a graceful termination:
sudo kill -TERM <PID>
Force Termination
If the process doesn’t terminate gracefully:
sudo kill -KILL <PID>
Using lsof Directly
You can combine the finding and killing steps:
sudo kill -9 $(sudo lsof -ti :3000)
This command finds all PIDs on port 3000 and forcefully terminates them.
Multiple Processes
If multiple processes are using the port:
sudo kill -9 $(sudo lsof -ti :3000 | tr '\n' ' ')
Alternative Methods
Using ps and grep
If lsof isn’t available or you prefer using ps:
sudo ps aux | grep -i port
sudo ps aux | grep -i 3000
Using Activity Monitor (GUI)
For those who prefer graphical interface:
- Open Activity Monitor (Applications > Utilities > Activity Monitor)
- Click on the “Network” tab
- Sort by “Port” column
- Find processes using port 3000
- Select and click “Quit Process”
Using Process Names
If you know the process name (like Rails or Node.js):
sudo killall rails
sudo killall node
Preventing Future Issues
Development Server Best Practices
-
Always stop servers gracefully:
bash# Rails Ctrl+C # or pkill -f "rails server" # Node.js Ctrl+C # or pkill -f "node server.js" -
Use process managers:
- For Rails: use
puma-devorforeman - For Node.js: use
nodemonwith--signal SIGTERM
- For Rails: use
-
Configure proper port handling:
bash# Rails - add to config/environments/development.rb config.server = :puma, { debug: true, workers: 0 } # Node.js - handle SIGTERM process.on('SIGTERM', () => { server.close(() => { console.log('Process terminated'); process.exit(0); }); });
Automatic Port Recovery
Create an alias in your shell profile:
alias killport="sudo kill -9 \$(sudo lsof -ti :3000)"
Then simply run:
killport
Advanced Troubleshooting
Checking for Zombie Processes
Sometimes processes appear dead but still hold ports:
sudo ps aux | grep -E '(Z|defunct)'
sudo kill -9 <zombie_pid>
Port Status Checking
Verify the port is actually free:
nc -zv localhost 3000
# or
telnet localhost 3000
System-wide Port Monitoring
Monitor all active ports:
sudo lsof -i -P | grep -i "listen"
Docker Container Issues
If using Docker, check for orphaned containers:
docker ps -a
docker rm <container_id>
Time_wait State
Sometimes ports remain in TIME_WAIT state:
sudo sysctl -w net.inet.tcp.msl=1000
Conclusion
- Always start with
sudo lsof -i :3000to identify processes using port 3000 on macOS - Use
kill -TERMfirst for graceful termination, thenkill -KILLif needed - Combine commands with
sudo kill -9 $(sudo lsof -ti :3000)for quick resolution - Prevent issues by using proper process managers and graceful shutdown procedures
- Create aliases like
killportfor frequent port clearing operations - Consider GUI alternatives like Activity Monitor if you prefer visual tools
For Rails and Node.js developers, implementing proper signal handling in your applications will prevent most port binding issues and ensure clean shutdowns.