端口被占用:客户端起不来的排查法

客户端点了图标没反应,或者启动后一直转圈、任务栏图标闪一下就没了——这类"起不来"的问题,八成都不是软件坏了,而是**它要监听的端口被别的程序占了**。

代理类客户端通常要在一个本地端口上监听(常见 7890、7891、1080 这类),如果那个端口已经有程序在用,新进程绑定失败,表现就是启动即退出,而且很多客户端不会弹错误框。

第一步:确认是不是端口问题

先手动启动一次,看有没有输出。命令行启动最直接:

# macOS / Linux
/Applications/YourApp.app/Contents/MacOS/YourApp

# Windows(在安装目录里)
YourApp.exe

如果看到 bind: address already in use、EADDRINUSE、或者中文的"端口占用",就可以确诊了。

第二步:找到是谁占的

Windows

# 查 7890 端口被谁占了
netstat -ano | findstr :7890

# 最后一列是 PID,用 PID 查进程名
tasklist | findstr 12345

macOS / Linux

# 两种写法都行
lsof -i :7890
ss -lptn 'sport = :7890'

输出里会直接给出进程名和 PID。知道是谁之后,判断就简单了:

占用者说明处理
同一个客户端的另一个实例重复启动、托盘里还留着一个退出所有实例再启动
旧版本残留进程升级后旧进程没退出结束进程,必要时重启
另一个代理工具两套工具抢同一个端口改端口,或只留一个
系统进程(Windows 的 SYSTEM)系统服务占用换端口,别杀系统进程
没有进程,但显示占用TIME_WAIT 未释放等 1–2 分钟,或换端口

第三种情况最容易被误判:TIME_WAIT

有时候 netstat 能看到端口在监听,但 lsof 找不到进程——因为连接已经关闭,只是 TCP 还在 TIME_WAIT 状态,要等 2 倍 MSL(通常 60 秒左右)才释放。

这不是故障,等一会儿就好。但如果你**刚关掉旧实例就立刻启动新的**,就会正好撞上这段窗口期,表现成"昨天还好好的,今天突然起不来"。

第四种:SYSTEM 进程占着不放

Windows 上有时 netstat 显示占用者是 PID 4(SYSTEM)。这种情况通常是系统服务(比如某些安全软件、虚拟化组件)绑定了这个端口。

不要试图结束 PID 4,那是系统进程。正确处理是换一个端口:

  1. 在客户端设置里把本地监听端口从 7890 改成 7891 或 7897
  2. 如果有程序手动填过 7890(比如命令行里的 http_proxy),一并改掉
  3. 重启客户端确认

换端口之后,别忘了这些地方

端口不是只改客户端就完事,下面这些地方也要跟着改,否则会出现"能连上但没网":

  • 环境变量:http_proxy / https_proxy 里写死的端口
  • git / npm / pip 各自的代理配置
  • 浏览器插件(SwitchyOmega 之类)里的代理服务器设置
  • 其他软件(Docker、IDE、下载工具)里手动配过的代理

判断口诀

一句话:起不来先看端口,端口先看占用,占用先看是不是自己。

大部分"端口被占用"其实是自己开了两份,或者旧进程没退干净。真正需要换端口的场景不到三成。

💡 一个快速验证:把客户端端口临时改成 17890 再启动。能起来,就确认是端口冲突;起不来,问题在别处(权限、防火墙、安装损坏)。

延伸阅读:连接失败怎么排查、TUN 模式和系统代理、延迟怎么测才准。