端口冲突排查:lsof / netstat / ss 三条命令和高频端口速查

· 约 3 分钟 🔌 TCP/UDP 端口表

Error: listen EADDRINUSE: address already in use :::3000 —— 开发时最常见的报错之一。端口被占了,快速找到谁在用、怎么处理,是每个后端开发的基本功。

三个操作系统的排查命令

macOS

# 查谁占用了 3000 端口
lsof -i :3000

# 输出示例:
# COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
# node    12345 user   23u  IPv6 0x...      0t0  TCP *:3000 (LISTEN)

# 只输出 PID(方便传给 kill)
lsof -t -i :3000

# 一行杀掉
kill -9 $(lsof -t -i :3000)

# 查所有监听中的端口
lsof -i -P -n | grep LISTEN

Linux

# ss(现代工具,比 netstat 快)
ss -tlnp | grep :3000
# t=TCP, l=listening, n=不解析域名, p=显示进程

# 输出示例:
# LISTEN 0  128  *:3000  *:*  users:(("node",pid=12345,fd=23))

# 查所有监听端口
ss -tlnp

# 老工具 netstat(部分系统需要安装 net-tools)
netstat -tlnp | grep :3000

# 一行杀掉
fuser -k 3000/tcp

Windows(PowerShell / CMD)

:: 查端口占用,找 PID
netstat -ano | findstr :3000

:: 输出示例:
:: TCP  0.0.0.0:3000  0.0.0.0:0  LISTENING  12345

:: 查 PID 对应的进程名
tasklist | findstr "12345"

:: 杀掉进程
taskkill /PID 12345 /F

:: PowerShell 一行搞定
Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess

端口号的三个区间

0        1023      49151     65535
|--------|---------|---------|
 知名端口  注册端口   动态端口
(需root) (应用层)  (临时连接)

开发项目惯例:选 3000-9999 范围,不会和系统服务冲突,也不会被操作系统随机分配给临时连接。

开发常用端口速查

Web 服务

端口服务备注
80HTTP需 root
443HTTPS需 root
3000Node.js 开发惯例React/Next.js 默认
4321Astro dev
5173Vite dev
8080HTTP 备用 / Tomcat不需要 root
8443HTTPS 备用

数据库

端口服务
3306MySQL / MariaDB
5432PostgreSQL
27017MongoDB
6379Redis
9200Elasticsearch HTTP
9300Elasticsearch 节点间通信
5984CouchDB

消息队列 / 流

端口服务
5672RabbitMQ AMQP
15672RabbitMQ 管理界面
9092Kafka
2181ZooKeeper

基础设施

端口服务
22SSH
21FTP 控制
20FTP 数据
25SMTP
53DNS
123NTP
3389Windows 远程桌面(RDP)

容器 / 编排

端口服务
2375Docker daemon(HTTP,不安全)
2376Docker daemon(HTTPS)
6443Kubernetes API Server
10250kubelet API
2379-2380etcd

常见冲突场景

场景一:本机多个项目同时开发

项目 A 默认 3000,项目 B 也默认 3000。

# 方法一:启动时指定不同端口
PORT=3001 npm start     # 项目 B 改用 3001

# 方法二:.env 文件写死各项目端口
# 项目A: PORT=3000
# 项目B: PORT=3001

场景二:Docker 容器宿主机冲突

# 查宿主机 8080 是谁在用
lsof -i :8080

# 改 docker run 的端口映射
docker run -p 8081:80 myapp  # 用 8081 替代 8080

场景三:服务 crash 后快速重启报错

# 等 TIME_WAIT 超时(1-2 分钟)

# 或者直接找残留进程
lsof -i :3000
kill -9 <PID>

# Linux 加速:修改内核参数(重启后生效)
echo "net.ipv4.tcp_tw_reuse=1" >> /etc/sysctl.conf

防火墙端口管理

开放端口到外网前确认服务是否需要公网访问:

# Linux iptables 开放 8080
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT

# firewalld(RHEL/CentOS 7+)
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload

# ufw(Ubuntu)
ufw allow 8080/tcp

数据库(MySQL 3306、Redis 6379)不应该直接开放公网端口,通过 VPN 或 SSH 隧道访问:

# SSH 隧道把远程 3306 映射到本地 3307
ssh -L 3307:127.0.0.1:3306 user@remote-host

配套工具

❓ 常见问题

端口被占用怎么快速找到并杀掉进程?

三步走:(1) 找 PID:macOS/Linux 用 lsof -i :端口号ss -tlnp | grep :端口号,Windows 用 netstat -ano | findstr :端口号;(2) 查进程名:ps -p PID -o comm=(Linux/macOS)或任务管理器(Windows);(3) 杀进程:kill PID(正常)或 kill -9 PID(强制);Windows 用 taskkill /PID xxx /F。一行命令搞定(macOS/Linux):kill -9 $(lsof -t -i :3000) 直接杀掉占用 3000 端口的进程。

端口号有什么范围规律?

三个范围,权限和用途不同:(1) 知名端口(0-1023)——由 IANA 分配给系统服务,监听需要 root 权限;HTTP 80、HTTPS 443、SSH 22、FTP 21 都在这里;(2) 注册端口(1024-49151)——常见应用和中间件,MySQL 3306、Redis 6379、PostgreSQL 5432、Nginx 8080;(3) 动态/私有端口(49152-65535)——客户端发起连接时系统随机分配的临时端口,不应该手动绑定服务到这个范围。开发项目惯例用 3000-9999,不容易和系统服务冲突。

LISTEN 和 ESTABLISHED 有什么区别?

LISTEN 是服务器在等待连接,ESTABLISHED 是连接已建立netstat -an 输出里:LISTEN —— 该端口正在监听,等待客户端连入,是服务端的状态;ESTABLISHED —— 已建立的 TCP 连接,客户端和服务端都有这个状态;TIME_WAIT —— 连接刚关闭,等待确认对端也关闭(约 60-120 秒),期间端口号还被占用;CLOSE_WAIT —— 对端已关闭,本端还没关,通常是代码没有正确 close socket。排查端口占用主要看 LISTEN 状态;排查连接数过多看 ESTABLISHED + TIME_WAIT 数量。

为什么服务重启后端口还是被占用?

TIME_WAIT 状态导致的"假占用"——TCP 四次挥手后,主动关闭方会进入 TIME_WAIT 状态约 2×MSL(60-120 秒),期间相同的 {源IP:源端口:目标IP:目标端口} 四元组不能复用。表现:服务 crash 后立刻重启,bind() failed: address already in use。解法:(1) 等 60-120 秒再重启;(2) 设置 SO_REUSEADDR socket 选项(大多数服务端框架默认开启);(3) Linux 内核参数 net.ipv4.tcp_tw_reuse=1(允许客户端复用 TIME_WAIT 端口,不影响服务端 LISTEN)。注意:SO_REUSEPORTSO_REUSEADDR 不同,前者允许多个进程绑定同一端口做负载均衡。

Docker 容器的端口映射怎么排查?

容器内端口和宿主机端口是两套,要分别查。宿主机视角:docker ps 看 PORTS 列(如 0.0.0.0:8080->80/tcp 表示宿主机 8080 → 容器 80);或 docker port 容器名 80 查容器 80 映射到宿主机哪个端口。容器视角:docker exec -it 容器名 ss -tlnp 在容器内查监听端口。冲突场景:宿主机已有服务在 8080,再启动一个 docker run -p 8080:80 会报错——用 lsof -i :8080 找宿主机上的冲突进程。

🔌 打开 TCP/UDP 端口表 130+ 常用端口按 12 类整理·HTTP 80/443·SSH 22·MySQL 3306·Redis 6379·MongoDB 27017·Docker 2375·K8s 6443·公网暴露风险标记