端口被占用怎么办?EADDRINUSE / Port already in use 全平台解决指南
现象:项目起不来,一行报错
Error: listen EADDRINUSE: address already in use :::3000
或英文形态:
Port 3000 is already in use
含义一句话:你要监听的端口已经被另一个进程占着。开发服务器、数据库、Docker 容器、上一个没退干净的 node 进程——都可能是占用者。
第一步:查出谁在占端口
macOS / Linux
lsof -ti:3000 # 只打印占用 3000 端口的进程 PID(脚本友好)
lsof -i:3000 # 人读版:PID、进程名、用户一目了然
Windows(PowerShell)
netstat -ano | findstr :3000 # 最后一列是 PID
tasklist /fi "PID eq 12345" # 用 PID 查进程名
第二步:处理占用进程
情况 A:旧的开发服务器(最常见)
上次 Ctrl+C 没杀干净,或者终端关了进程还活着。直接结束它:
# macOS / Linux
kill -9 $(lsof -ti:3000)
# Windows(PowerShell)
taskkill /PID 12345 /F
判断依据:lsof -i:3000 显示的进程名是你自己的(node、vite、next-server 等)→ 放心杀。
情况 B:是别的服务在用这个端口
进程名不是你的项目(比如 postgres、mongod、另一个团队的服务)——别杀它,换自己的端口:
# 按框架改启动端口
next dev -p 3001 # Next.js
vite --port 3001 # Vite
npm start -- --port 3001 # 多数 CLI 支持
情况 C:Docker 容器映射了该端口
lsof 里进程名是 docker-proxy:
docker ps --filter "publish=3000" # 找到容器
docker stop <容器名> # 停掉,或改 compose 里的端口映射
为什么要 kill -9?kill 不行吗?
先试普通 kill(发 SIGTERM,进程可以优雅退出),几秒后还在再 kill -9(SIGKILL,强杀)。开发场景的残留进程通常无所谓优雅,直接 -9 省事;生产数据库等有状态服务永远先用普通 kill。
预防:让端口冲突不再发生
- 固定开发端口约定:团队约定 3000/3001/3002 分工,别抢;
- 用 ports 变量:
.env里放PORT=3001,配置引用变量而不是硬编码; - 退出走 Ctrl+C 而不是关终端:大多数 dev server 会随终端会话清理,但后台启动(
&/nohup)的不会——后台起的进程要记 PID; - 端口 0 = 随机分配:写测试/脚本时监听
port 0让系统分配空闲端口,从根上避开冲突。
高频追问
3000 端口在 Mac 上查出来是 ControlCenter?
macOS Monterey 起系统服务会占用若干端口(AirPlay 接收器常占 5000/7000)。ControlCenter 占 3000 属系统行为,别杀,改用自己的端口最省事。
杀完进程端口还是占用?
两种可能:①进程处于 TIME_WAIT 状态(一分钟内自动释放,等一下再试);②有父进程拉起了新的子进程(Docker restart 策略、pm2、systemd)——找到管理者停它,而不是反复杀子进程。
EADDRINUSE 里 :::3000 的三个冒号是什么?
::: 是 IPv6 全地址 :: 加端口分隔符——你的服务试图监听 IPv6 的 3000 端口。与 IPv4 的 0.0.0.0:3000 是两个不同的监听,但多数程序(和这个报错场景)双栈共享,按占用处理即可。
一键脚本(放 alias 里)
# macOS/Linux:释放指定端口
freeport() { lsof -ti:"$1" | xargs kill -9 2>/dev/null && echo "port $1 freed" || echo "port $1 was free"; }
# 用法:freeport 3000
Windows 版(PowerShell profile):
function freeport($p) { Get-NetTCPConnection -LocalPort $p -ErrorAction SilentlyContinue |
ForEach-Object { Stop-Process -Id $_.OwningProcess -Force } }
排查清单
lsof -ti:3000(Windows:netstat -ano | findstr :3000)拿到 PID- 看进程名:自己的残留 → 杀;别人的服务 → 换端口;docker-proxy → 停容器
- 杀完还占:等 TIME_WAIT 或找进程管理者
- 长期方案:端口约定进 .env、后台进程记 PID、脚本用 port 0
本文由 ToolVault 工具匣 提供。开发部署相关工具:Dockerfile 生成器、Linux 命令速查、HTTP 状态码速查。访问 首页 查看更多开发者工具。