报错信息说明了什么
Clash 系客户端(包括基于 mihomo 内核的各类图形界面)启动时会尝试监听一组本地端口,用于接收系统或浏览器发来的代理请求。最常见的一个是混合端口 7890(mixed-port),它同时接受 HTTP 与 SOCKS5 两种协议的连接。如果这个端口已经被另一个程序占用,内核会在日志里抛出类似下面的错误并直接退出:
FATA[0000] Start Mixin server error: listen tcp 127.0.0.1:7890: bind: address already in use
这条日志的关键是 bind: address already in use——它明确说明问题不在订阅、不在规则,而是操作系统层面这个端口号已经被占用,新进程无法再绑定同一个端口。常见的还有 7891(部分客户端的 SOCKS 端口)、9090(外部控制端口 external-controller)、53(DNS 监听端口)。定位思路完全一致,本文以最常遇到的 7890 为例展开。
端口占用和订阅失效、节点不可用是两类完全不同的问题。前者表现为客户端无法启动或启动后立刻退出;后者是客户端能正常运行,只是连不上目标网站。先看清报错阶段再排查,能省不少时间。
谁最容易占用 7890
7890 并不是系统保留端口,理论上任何程序都可能抢先占用它,但实际排查中出现频率最高的几类情况是:
- 同一台机器上跑了两个 Clash 类客户端。比如同时装了 Clash Verge Rev 和 Clash Plus,又都用默认的 7890,前一个没退干净,后一个自然抢不到端口。
- 上一次进程没有正常退出。系统休眠、强制结束任务管理器进程、内核崩溃但主程序未清理子进程,都会留下一个僵尸进程继续占着端口。
- 其他代理工具使用了相同默认端口。部分老版本代理工具、抓包工具(如某些配置下的调试代理)默认也监听 7890 或相近号段。
- Docker 容器或 WSL2 内部服务做了端口映射,把容器内的服务映射到主机的 7890。
无论是哪一种,处理思路都是先确认占用者是谁,再决定是关闭它还是换个端口给 Clash 用。盲目重启电脑有时能临时解决,但不清楚成因下次还会复发。
Windows 下用 netstat 定位占用进程
打开命令提示符或 PowerShell,执行:
netstat -ano | findstr :7890
正常情况下会输出类似这样的一行或多行:
TCP 127.0.0.1:7890 0.0.0.0:0 LISTENING 18420
最后一列 18420 就是占用该端口的进程 PID。接下来用这个 PID 反查进程名:
tasklist | findstr 18420
如果输出显示是上一次未退出的客户端主进程(比如 clash-verge.exe 或 mihomo.exe),说明确实是残留进程,直接在任务管理器里手动结束该进程,或执行:
taskkill /PID 18420 /F
结束后重新启动客户端即可。如果 PID 对应的是一个陌生程序,先确认它的作用,再考虑关闭该程序或修改 Clash 的监听端口(见后文)。
不要在不了解进程用途的情况下直接 taskkill。如果查到的 PID 是系统服务或安全软件,强行结束可能引发其他异常,遇到这种情况优先选择改端口而不是杀进程。
macOS / Linux 下用 lsof 定位占用进程
macOS 与大多数 Linux 发行版都自带 lsof(List Open Files),用它查端口比 netstat 更直观:
lsof -i :7890
输出示例:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mihomo 22187 alice 7u IPv4 0x1a2b 0t0 TCP 127.0.0.1:7890 (LISTEN)
COMMAND 列直接给出进程名,PID 列是进程号。确认是残留的 Clash 内核进程后,结束它:
kill -9 22187
如果系统没有 lsof(部分精简版 Linux 容器),可以用 ss 命令替代:
ss -tlnp | grep 7890
该命令同样会在末尾给出 pid= 字段,操作方式与前面一致。Linux 下如果占用端口的是普通用户权限不足以结束的进程,需要在命令前加 sudo。
方法一:在客户端界面直接改端口
如果占用 7890 的是一个不方便关闭的常驻程序(比如另一款需要长期运行的工具),更省事的做法是让 Clash 换一个端口,而不是去动别人。多数图形客户端都在设置界面里提供了端口修改入口,操作路径通常是:
-
打开客户端设置面板
在主界面找到"设置"或齿轮图标,进入网络 / 端口相关的配置分区,不同客户端命名略有差异,但都会集中列出混合端口、HTTP 端口、SOCKS 端口等字段。
-
找到混合端口(Mixed Port)字段
把原本的
7890改成一个未被占用的端口号,例如17890或7899。建议选择 1024 以上、10000 以下且不常见的号段,避免再撞上别的软件。 -
保存并重启核心
多数客户端修改端口后需要点击"重启内核"或"应用"按钮才会生效,单纯保存设置页可能不会立即重新绑定端口。
-
同步更新系统代理端口
如果客户端开启了"设置为系统代理"功能,修改混合端口后务必确认系统代理设置里的端口号也已经同步更新,否则会出现内核正常运行但流量依然连不上的情况。
方法二:直接修改配置文件里的端口字段
如果你使用的是手动维护的配置文件,或者客户端界面暂时无法访问,也可以直接编辑 YAML 配置。找到订阅配置文件里下面几行(字段名可能因版本而略有差异):
mixed-port: 7890
allow-lan: true
external-controller: 127.0.0.1:9090
把 mixed-port 后面的数值改成一个空闲端口即可,例如:
mixed-port: 17890
如果客户端同时使用了独立的 HTTP 端口和 SOCKS 端口(而非统一的 mixed-port),对应字段通常是:
port: 7890
socks-port: 7891
按需分别修改。注意 external-controller 用的是另一个端口(默认 9090),它是给面板 / 仪表盘用的管理接口,和流量转发端口是两回事,如果报错信息里提到的是 9090 被占用,应该改这一行而不是 mixed-port。修改保存后重启客户端或重新加载配置,新端口才会生效。
手动改配置文件后,如果客户端设置为"自动更新订阅覆盖本地配置",下次刷新订阅时你的端口改动可能被订阅内容覆盖回默认值。长期使用的自定义端口建议同时在客户端界面里设置一次,两处保持一致。
修改端口后需要重新检查的三处
端口号改动后,原来依赖 7890 的一些配置也需要同步调整,否则会出现"客户端已启动,但浏览不了网页"的新问题:
- 浏览器插件里的代理端口。如果通过 SwitchyOmega 之类的浏览器插件手动配置了代理地址
127.0.0.1:7890,改端口后插件里的端口号也要同步修改。 - 系统级代理设置。Windows 的"设置 → 网络和 Internet → 代理"、macOS 的"系统设置 → 网络 → 代理"里如果手动填过端口号,同样要更新。
- TUN 模式不受影响。如果启用的是 TUN 模式而非系统代理,流量走的是虚拟网卡而非 mixed-port,这种情况下改端口通常不会影响已有的 TUN 配置,但仍建议重启一次客户端确认内核完全重新加载。
确认端口已经空闲的验证方法
结束占用进程或改完端口后,不要凭感觉认为"应该好了",用命令再确认一次最省心。Windows 下重新执行:
netstat -ano | findstr :7890
如果没有任何输出,说明该端口目前处于空闲状态,可以放心使用。macOS / Linux 下对应执行:
lsof -i :7890
同样,无输出即代表端口空闲。之后再启动 Clash 客户端,正常情况下日志里会出现类似下面的成功提示,而不是之前的 FATA 级错误:
INFO[0000] Mixed(http+socks) proxy listening at: 127.0.0.1:7890
看到这一行代表混合端口绑定成功,客户端已经进入正常监听状态,可以继续配置系统代理或浏览器插件。
如果改完端口问题依旧存在
极少数情况下,即便换了一个"看起来空闲"的端口依然报同样的绑定错误,可以按下面几点继续排查:
-
确认改动的是正在加载的那份配置
部分客户端有多套配置文件(profile),修改了 A 份但客户端实际加载的是 B 份,改动自然不会生效。
-
检查是否有安全软件拦截了端口监听
部分安全防护软件会拦截未知程序对本地端口的绑定行为,把 Clash 客户端加入信任名单或临时关闭相关拦截项后再测试。
-
换一个完全不常见的端口号重新测试
有些号段被系统或其他后台服务保留,换成五位数、非整千的端口号(如 27891)再试一次,排除号段本身的问题。
把这些环节挨个确认一遍,基本能覆盖端口占用类问题的绝大多数场景。这类故障的核心始终是同一句话:先用系统命令确认端口到底被谁占了,再决定关闭对方还是给 Clash 换一个端口,不需要重装客户端或重新下载订阅。