先看报错地址,再决定关进程还是改端口

处理顺序:确认失败的监听端口 → 找到占用进程 → 退出重复实例,或换一个空闲端口 → 同步系统代理。不要先删订阅,也不要反复重装。端口冲突发生在本地监听阶段,通常与远端代理节点是否可用无关。

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内核控制 API9090 是常见示例,不能当作上网代理端口
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。没有监听输出只能说明查询当时未发现对应监听者,仍要以重启后的绑定结果为准。

  1. 在当前客户端找到“混合端口”或“Mixed Port”设置,记下旧值。菜单名称随客户端版本不同,不要把内核控制端口当成混合端口。
  2. 将混合端口改为 17890,保存,并按客户端提示重载或重启内核。
  3. 检查运行日志,确认不再出现对应端口的绑定失败。
  4. 重新查询监听列表,确认 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,系统代理与应用代理也指向同一入口。如果以后准备停用客户端,先关闭系统代理再退出,避免系统继续向已经停止的本地端口发起连接。