Clash 端口被占用怎么办:定位 7890 冲突进程并修改混合端口

客户端启动报端口占用时,用 netstat、lsof、ss 三类命令找出占用进程,再讲如何在 mixed-port 字段与系统代理设置里同步改端口,防止改完不生效。

先确认冲突的是哪个端口

出现“address already in use”“bind failed”或“端口已被占用”时,结论通常很直接:Mihomo 内核准备监听某个本地端口,但该端口已经被另一个进程占用。常见冲突端口是 7890,也可能是 78919090 或配置中自定义的数值。

mixed-port 是混合代理端口,同一个监听入口可以接收 HTTP 代理和 SOCKS5 代理连接。很多 Clash 客户端默认把它设为 7890。浏览器扩展、系统代理和命令行工具通常都会连接这个端口,因此它发生冲突时,最直观的结果就是内核启动失败或代理无法连接。

配置字段 常见端口 用途 是否能与 mixed-port 重复
mixed-port 7890 同时接受 HTTP 与 SOCKS5 代理 自身只能被一个进程监听
port 7890 仅提供 HTTP 代理 不能使用同一监听地址和端口
socks-port 7891 仅提供 SOCKS5 代理 不能使用同一监听地址和端口
external-controller 9090 提供控制接口,不承载普通代理流量 应使用独立端口

从日志中提取准确端口

先打开客户端的日志页面,搜索 bindlistenaddress already in use端口。如果日志出现 listen tcp 127.0.0.1:7890,需要排查的是 TCP 7890;如果出现 0.0.0.0:7890,表示程序准备在所有本机网络接口上监听该端口,冲突范围比只监听 127.0.0.1 更大。

还要检查同一份配置是否同时写了 mixed-port: 7890port: 7890。这种情况不需要寻找外部程序,因为配置本身就在要求两个监听器争用同一个地址。保留混合端口,删除不需要的独立 HTTP 或 SOCKS 端口即可。

Windows 用 netstat 定位 7890 占用进程

Windows 10 与 Windows 11 都可以使用系统自带的 netstat。先完全退出当前 Clash 客户端,再以管理员身份打开“终端”或“命令提示符”,执行下面的命令:

netstat -ano | findstr :7890

典型结果如下。最后一列的 16420 是进程标识符,也就是 PID:

TCP    127.0.0.1:7890    0.0.0.0:0    LISTENING    16420

只有状态为 LISTENING 的记录表示某个程序正在监听该 TCP 端口。若结果只是远端地址中包含 :7890,不能直接认定本地端口被占用。应重点核对“本地地址”一列是否为 127.0.0.1:78900.0.0.0:7890[::]:7890

根据 PID 查询程序名称

取得 PID 后继续执行:

tasklist /FI "PID eq 16420"

也可以在 PowerShell 中查看程序路径:

Get-Process -Id 16420
Get-CimInstance Win32_Process -Filter "ProcessId = 16420" |
  Select-Object ProcessId, Name, ExecutablePath, CommandLine

如果结果是另一个 Clash、Mihomo、sing-box 或代理客户端,通常说明旧内核没有随界面退出。先从该客户端菜单正常退出,再等待 3 至 5 秒重新查询端口。任务管理器中只关闭窗口并不一定结束后台内核,托盘区仍可能保留运行图标。

如果确认进程可以结束,可在任务管理器的“详细信息”页按 PID 定位,也可以执行:

taskkill /PID 16420 /F

netstat 没结果但仍报错

  • 确认日志中的端口确实是 7890,不要把控制端口 9090 当成混合端口。
  • 同时检查 IPv4 与 IPv6。监听 [::]:7890 的程序可能阻止另一个进程绑定 IPv4 地址。
  • 退出客户端后重新执行命令,避免把当前客户端自己的正常监听误判为冲突。
  • 检查客户端是否重复启动了两个内核实例,例如便携版和安装版同时设置为开机启动。
  • 查看日志中是否实际提示权限不足。权限错误与端口占用的处理方法不同。

macOS 用 lsof 查找监听程序

macOS 可以用 lsof 查看哪个进程打开了 TCP 7890。打开“终端”,执行:

sudo lsof -nP -iTCP:7890 -sTCP:LISTEN

-nP 会直接显示数字地址和端口,避免域名解析影响速度。结果中的 COMMAND 是进程名称,PID 是进程编号。例如:

COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mihomo   8421 user   10u  IPv4        0t0      TCP 127.0.0.1:7890 (LISTEN)

继续用下面的命令检查启动参数,判断它属于哪个客户端:

ps -p 8421 -o pid,ppid,user,command

若进程来自另一个仍在运行的代理客户端,应优先从菜单栏图标正常退出。确认进程已经失去响应后,先发送普通终止信号:

kill 8421

等待几秒后再次运行 lsof。只有普通终止无效时才考虑 kill -9 8421。强制结束可能让客户端来不及保存当前配置,因此不应作为第一步。

同时排查独立 SOCKS 端口

如果配置还启用了 socks-port: 7891,应分别查询 7890 和 7891。混合端口改成 7892,并不能解决另一个独立监听器在 7891 上发生的冲突:

sudo lsof -nP -iTCP:7890 -sTCP:LISTEN
sudo lsof -nP -iTCP:7891 -sTCP:LISTEN
sudo lsof -nP -iTCP:9090 -sTCP:LISTEN

Linux 用 ss 检查端口监听

多数现代 Linux 发行版默认提供 ss。它可以直接显示监听套接字及对应进程。执行:

sudo ss -ltnp 'sport = :7890'

参数中的 l 表示只看监听状态,t 表示 TCP,n 表示直接显示数字端口,p 表示显示进程。也可以使用兼容性更直观的筛选方式:

sudo ss -ltnp | grep ':7890'

结果可能类似:

LISTEN 0 4096 127.0.0.1:7890 0.0.0.0:* users:(("mihomo",pid=2317,fd=8))

如果 Mihomo 由 systemd 管理,不要只用 kill 结束进程,因为服务管理器可能立即将它重新拉起。先查询服务状态,再停止对应单元:

systemctl --type=service --state=running | grep -Ei 'mihomo|clash'
sudo systemctl status mihomo
sudo systemctl stop mihomo

容器环境还要检查端口映射。宿主机上的 Docker 或 Podman 代理进程可能占用 7890,即使容器内并没有名为 Mihomo 的宿主机进程:

docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Ports}}'
podman ps --format 'table {{.ID}}\t{{.Names}}\t{{.Ports}}'

修改 mixed-port 与客户端监听端口

如果占用 7890 的程序必须保留,最稳妥的处理方式是给 Clash 或 Mihomo 换一个未使用端口,例如 7892。先用前面的系统命令确认 7892 没有监听记录,再修改客户端。

从图形界面修改

带图形界面的客户端通常可以从「设置」→「参数设置」→「混合端口」进入。把 7890 改为 7892,保存后重启内核。不同客户端的菜单名称可能写成“Mixed Port”“混合代理端口”或“端口设置”,但需要修改的目标都是当前内核的 mixed-port

如果页面同时列出 HTTP 端口、SOCKS 端口和混合端口,不要给多个项目填写相同数值。只需要单一入口时,可启用混合端口并关闭不使用的独立监听项,从而减少冲突点。

直接编辑 YAML 配置

在配置文件中,将字段改为:

mixed-port: 7892
allow-lan: false
mode: rule
log-level: info

mixed-port 必须是整数,不能写成带冒号的地址,也不能与同一配置中的 portsocks-port 或控制接口重复。保存后需要让内核重新加载配置;仅修改磁盘文件,不会自动改变已经运行的监听器。

多个 Profile 并存时,要确认编辑的是当前启用配置。部分客户端会把订阅内容复制到应用数据目录,订阅原始文件与运行时配置并不是同一个文件。可先在界面查看当前 Profile 名称,再从该配置的编辑入口进入,避免改到未启用的副本。

验证新端口已经监听

重启内核后不要立刻只看网页是否能打开。先确认系统确实出现了新监听器,并且旧端口不再属于当前客户端:

# Windows
netstat -ano | findstr :7892

# macOS
sudo lsof -nP -iTCP:7892 -sTCP:LISTEN

# Linux
sudo ss -ltnp 'sport = :7892'

预期结果是本机地址 127.0.0.1:7892 或客户端明确配置的监听地址处于 LISTEN 状态。若客户端允许局域网连接,可能显示 0.0.0.0:7892;此时还应检查访问控制与防火墙规则,不要仅为解决本机冲突而扩大监听范围。

同步修改系统代理与应用代理

端口改完但网页仍打不开,最常见原因是系统代理还指向旧的 127.0.0.1:7890。内核已经在 7892 正常运行,而浏览器继续连接 7890,表现就会像“修改没有生效”。

优先让客户端重新设置系统代理

  1. 关闭客户端中的“系统代理”开关。
  2. 确认混合端口已保存为 7892,并重启内核。
  3. 重新开启“系统代理”。
  4. 进入操作系统的代理页面,核对地址为 127.0.0.1、端口为 7892

Windows 11 可从「设置」→「网络和 Internet」→「代理」检查手动代理服务器。macOS 可从「系统设置」→「网络」→当前网络→「详细信息」→「代理」核对 Web 代理或安全 Web 代理。通常让客户端管理这些项目更稳妥,手动填写时必须与实际监听端口一致。

检查浏览器扩展和命令行变量

代理切换扩展可能绕过系统设置,仍保留旧端口。需要在扩展的代理配置中把 HTTP 或 SOCKS5 端口改为 7892。开发工具还可能通过环境变量指定代理,可分别检查:

HTTP_PROXY=http://127.0.0.1:7892
HTTPS_PROXY=http://127.0.0.1:7892
ALL_PROXY=socks5://127.0.0.1:7892

同一个 mixed-port 可以接收上面两类协议,但应用填写的协议前缀仍要正确。若配置的是独立 socks-port,则 ALL_PROXY 应指向那个独立端口,而不是机械照抄混合端口。

TUN 模式下的区别

TUN 模式会通过虚拟网络接口接管流量,正常情况下不依赖系统 HTTP 代理开关。不过,只要配置仍要求 Mihomo 创建 mixed-port: 7890,7890 被占用仍可能让内核启动失败。解决办法依然是关闭冲突进程或修改监听端口。

排查时建议暂时只保留一种接管方式:要么关闭 TUN,使用系统代理验证 7892;要么关闭系统代理,只验证 TUN。两种方式同时开启会增加变量,容易把 DNS、路由或浏览器扩展问题误认为端口冲突。

改完仍报占用的检查顺序

如果端口已经换成 7892,但日志仍提示 7890 被占用,说明运行时配置没有采用刚才的修改。按下面顺序检查,可以快速定位是配置、进程还是系统代理没有同步。

  1. 重新读取最新日志。确认报错时间发生在本次重启之后,并记录日志里的完整地址与端口。
  2. 确认当前 Profile。检查客户端当前选中的配置名称,避免编辑测试配置后仍运行订阅配置。
  3. 执行配置重载。保存 YAML 后使用客户端的“重新加载配置”或“重启内核”,不要只关闭设置窗口。
  4. 排查重复客户端。检查托盘、菜单栏、开机启动项、systemd 服务和容器,确认没有第二个内核实例。
  5. 检查字段重复。确认 mixed-portportsocks-portexternal-controller 没有使用同一个地址和端口。
  6. 确认新端口监听。用 netstat、lsof 或 ss 验证 7892,而不是只看客户端界面的“运行中”。
  7. 同步所有代理入口。更新系统代理、浏览器扩展、终端环境变量、开发工具和局域网设备中的旧端口。

用 curl 做最终验证

确认 7892 正常监听后,可让 curl 明确经过混合端口发起请求。下面的命令会显示连接过程和 HTTP 响应头:

curl -I -v -x http://127.0.0.1:7892 https://example.com

输出中应先出现连接 127.0.0.1:7892,随后建立到目标站点的 CONNECT 隧道。如果提示 Connection refused,表示该地址上没有可用监听器;如果连接成功但目标请求超时,则端口冲突已经解决,下一步应检查节点、规则、DNS 或网络连通性。

可复用的处理结论

  • 日志报 address already in use:先查监听进程,不要先改节点。
  • 旧代理程序占用 7890:退出旧程序并清理重复自启动。
  • 占用程序必须保留:把 mixed-port 改为已确认空闲的端口,例如 7892。
  • 内核已监听新端口但应用不能上网:同步修改系统代理和应用内代理。
  • 订阅更新后问题复发:把端口调整放入客户端的持久化覆写设置。
  • TUN 已启用仍启动失败:继续检查配置中的混合端口和控制端口是否冲突。
获取客户端 查看全平台选择