先看报错地址,再决定关进程还是改端口
处理顺序:确认失败的监听端口 → 找到占用进程 → 退出重复实例,或换一个空闲端口 → 同步系统代理。不要先删订阅,也不要反复重装。端口冲突发生在本地监听阶段,通常与远端代理节点是否可用无关。
Clash 系列客户端的图形界面负责管理配置,真正监听端口的可能是 Clash、Clash Meta(mihomo)内核,也可能是客户端启动的后台服务。关闭窗口不一定退出内核;托盘、开机启动项和服务模式都可能让监听继续存在。
从日志中提取三个信息
listen tcp 127.0.0.1:7890: bind: address already in use
这是一条示意日志,不是本机实测结果。它说明失败对象是 TCP 监听,地址是 127.0.0.1,端口是 7890。Windows 上还可能出现“通常每个套接字地址只允许使用一次”的提示。先记下实际数字,后面的命令都应查询日志里的端口。
| 配置字段 | 用途 | 排查重点 |
|---|---|---|
mixed-port | 同一入口接收 HTTP 与 SOCKS 代理连接 | 7890、7897 是常见设置,但不是固定标准 |
port / socks-port | 独立 HTTP / SOCKS 入口 | 检查是否与混合端口重复 |
external-controller | 内核控制 API | 9090 是常见示例,不能当作上网代理端口 |
dns.listen | 内核 DNS 监听地址 | 可能涉及 UDP 与 TCP,不能只查 TCP |
Windows:用监听端口找到 PID 与程序路径
打开 PowerShell,先查询本机 TCP 监听。下面以 7890 和 7897 为例。普通权限通常可以查看监听列表;读取其他用户进程的路径时,可能需要以管理员身份打开终端。
Get-NetTCPConnection -State Listen -LocalPort 7890,7897 -ErrorAction SilentlyContinue |
Select-Object LocalAddress,LocalPort,State,OwningProcess
重点看 OwningProcess,它是进程 PID。假设结果显示 PID 为 6420,继续查询名称与可执行文件路径。6420 只是演示值,操作时使用查询结果,不要原样结束这个数字对应的进程。
Get-Process -Id 6420 | Select-Object Id,ProcessName,Path
Get-CimInstance Win32_Process -Filter "ProcessId = 6420" |
Select-Object ProcessId,ParentProcessId,ExecutablePath,CommandLine
命令提示符也能查
netstat -ano -p tcp | findstr ":7890"
netstat -ano -p tcp | findstr ":7897"
tasklist /FI "PID eq 6420"
netstat 的输出同时包含本地地址和远程地址。筛选命令只是缩小范围,仍要确认本地地址的端口确实是 7890,并且状态为 LISTENING。远程地址带有 7890,或者状态为 TIME_WAIT,不能直接证明有程序正在占用本地监听端口。
- 路径指向另一套 Clash 客户端:从它的托盘菜单正常退出,再检查端口。
- 路径指向当前客户端内核:可能已经正常运行,也可能存在第二个启动实例,结合日志时间与父进程判断。
- 路径指向其他应用:优先调整 Clash 的端口,不要为了释放端口结束不相关程序。
- PID 很快变化:检查服务模式、任务管理器的“启动应用”和服务管理器,后台组件可能在自动重启。
确认是已经失去界面控制的残留内核后,才考虑执行 Stop-Process -Id 6420。结束进程会中断它的现有连接。若它属于服务,应先通过所属客户端停止服务,避免服务管理器马上重新拉起;不要批量结束所有名称含 Clash 的进程。
macOS 与 Linux:检查监听地址及后台服务
macOS:使用 lsof
sudo lsof -nP -iTCP:7890 -sTCP:LISTEN
sudo lsof -nP -iTCP:7897 -sTCP:LISTEN
ps -p 6420 -o pid,ppid,command
-nP 保留数字地址与端口,方便直接比对日志。lsof 会显示命令名、PID 和监听地址。优先从菜单栏退出旧客户端,再重新查询。如果监听者由后台服务启动,只关主窗口仍可能留下内核,应在对应客户端的服务设置中停止它。
Linux:使用 ss
sudo ss -ltnp 'sport = :7890'
sudo ss -ltnp 'sport = :7897'
ps -p 6420 -o pid,ppid,args
-l 只看监听,-t 看 TCP,-n 显示数字,-p 显示关联进程。若进程受 systemd 管理,应确认实际服务单元后再停止;不要猜测服务名。部分客户端使用用户服务,另一些使用系统服务,需要分别在用户级或系统级服务列表中确认。
普通残留进程可以先用 kill -TERM 6420 请求退出,再查询端口是否释放。不要一上来使用强制结束;先给进程正常收尾的机会。若结束后 PID 变化而端口仍在,说明应继续找自动启动来源,而不是重复杀进程。
修改 mixed-port:先检查新端口,再保存持久设置
如果占用者必须保留,就把 Clash 混合端口改到空闲值。例如计划使用 17890,先把前面查询命令里的端口替换为 17890。没有监听输出只能说明查询当时未发现对应监听者,仍要以重启后的绑定结果为准。
- 在当前客户端找到“混合端口”或“Mixed Port”设置,记下旧值。菜单名称随客户端版本不同,不要把内核控制端口当成混合端口。
- 将混合端口改为
17890,保存,并按客户端提示重载或重启内核。 - 检查运行日志,确认不再出现对应端口的绑定失败。
- 重新查询监听列表,确认 17890 的所属 PID 与当前客户端内核一致。
直接维护 YAML 时,只改需要的字段
mixed-port: 17890
allow-lan: false
这是顶层配置片段,不是完整订阅;应合并进已有配置,保留原有代理、策略组和规则。allow-lan: false 表示此示例不开放局域网访问。如果现有配置另有用途,应按实际需求保留,而不是整份覆盖。
检查同一份配置里的 port、socks-port、external-controller 及其他监听入口,避免让两个独立监听使用相同地址和端口。不要新增第二个同名 mixed-port 字段;重复键的处理结果可能随解析器而异。
订阅更新可能覆盖订阅文件,临时生成的运行配置也可能在重启时被重建。优先使用客户端持久化的端口设置,或其支持的覆写机制。若两处都配置了端口,应查看最终生效配置和日志,确认真正运行的是 17890。覆写的合并顺序由客户端决定,不能只凭编辑器里的一行判断。
更多字段用途可查阅混合端口配置说明;YAML 缩进规则见YAML 配置基础。这类本地监听参数不需要修改代理节点的服务器端口。
同步系统代理:改完端口还要更新连接入口
内核改到 17890,系统代理却还指向 7890,浏览器仍会连接失败。如果客户端负责设置系统代理,先关闭它的“系统代理”开关,再重新开启,让客户端刷新地址。之后查看系统设置核对结果,不要只看开关是否亮起。
- Windows 11:“设置” → “网络和 Internet” → “代理” → “手动设置代理” → “编辑”。核对地址
127.0.0.1和端口17890。Windows 10 对应页面通常使用“使用代理服务器”开关。 - macOS 13 及之后:“系统设置” → “网络” → 当前网络服务 → “详细信息” → “代理”。核对启用的网页代理、安全网页代理或 SOCKS 代理;使用混合端口时,可让所需入口指向同一个本地端口。
- Linux 桌面:在桌面环境的网络代理设置中检查手动代理。GNOME 与 KDE 的菜单位置不同,不能假设所有发行版都采用相同入口。
浏览器扩展、下载工具、IDE 和终端可能使用各自的代理地址,不一定跟随系统代理。把它们手动填写的 7890 或 7897 同步为 17890。终端环境变量修改后,旧终端或已启动的程序还可能保留原值,需要重新打开。
# 在当前 shell 中查看代理环境变量;不同 shell 的输出可能不同
env | grep -i proxy
# 在 PowerShell 中查看代理环境变量
Get-ChildItem Env: | Where-Object Name -Match 'proxy'
这些命令只负责查看,不会自动修改变量。特别检查 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 和 NO_PROXY。通过普通 HTTP 混合入口转发 HTTPS 网站时,HTTPS_PROXY 常见写法仍是 http://127.0.0.1:17890;变量名描述目标请求类型,并不要求本地代理使用 TLS。
验证修复:监听、代理入口、实际请求分别检查
修复后用一次明确指定代理地址的请求验证,避免被系统代理缓存或浏览器扩展干扰。下面使用保留的示例域名作为测试目标;它不是带宽测速,结果也不代表所有网站都能访问。
# Windows PowerShell:显式调用 curl.exe,避开旧版别名
curl.exe --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 15 -I https://example.com
# macOS / Linux
curl --proxy http://127.0.0.1:17890 --connect-timeout 5 --max-time 15 -I https://example.com
如果提示无法连接 127.0.0.1:17890,先查内核监听是否存在。如果已经连上本地代理,却出现目标连接超时、DNS 错误或 TLS 错误,则本地端口问题可能已经解决,应继续检查规则命中、目标解析和所选代理。HTTP 头或隧道响应只是排查线索,不要把任意状态码都当成整体连接正常。
查不到占用者时的补充检查
- 日志失败对象是 UDP:Windows 用
Get-NetUDPEndpoint -LocalPort 7890,Linux 用sudo ss -lunp 'sport = :7890',macOS 用sudo lsof -nP -iUDP:7890。把端口替换为实际报错值。 - Windows 报访问权限错误:用
netsh interface ipv4 show excludedportrange protocol=tcp查看排除范围,涉及 IPv6 时也检查对应 IPv6 范围。优先换到范围之外的空闲端口,不要直接删除系统保留项。 - 刚释放端口却仍失败:确认日志时间是本次启动,而不是界面保留的旧记录,再检查是否有自动重启的服务。
- 改端口后重启又恢复旧值:检查订阅更新、覆写优先级及客户端持久设置,找出实际写回配置的来源。
最后保留一份可复查记录
记录原端口、新端口、占用程序路径和修改位置即可。再次开机后,核对只有预期客户端监听 17890,系统代理与应用代理也指向同一入口。如果以后准备停用客户端,先关闭系统代理再退出,避免系统继续向已经停止的本地端口发起连接。