本人的开发环境经常遇到端口占用问题,nacos或spring工程启动失败原因均为诡异的未被使用端口报错端口占用。苦于没有一致的情况一直寻因无果,逐步排除终于找到底层因素,作此纪录。
查看端口占用
遇到端口占用问题,首先确认是否端口已占用:
# windows命令行
netstat -nao | findstr 8848
# 输出示例:
TCP 0.0.0.0:8848 0.0.0.0:0 LISTENING 42708
TCP [::]:8848 [::]:0 LISTENING 42708
TCP [::1]:8848 [::]:0 LISTENING 24002
如果有查询结果,杀掉进程就不用往下阅读了。
# 这里42708是上个命令得到的进程PID值
taskkill /F /PID 42708 /T
如果没有任何结果,请确认是否符合以下条件:
- 开发环境为windows
- 安装并启用了
Hyper-v
或WSL2
(DockerDesktop)
windows默认为Hyper-v/WSL2
分配了某些范围的端口,这些端口
并未“真正”地被使用所以无法查出占用,但也无法被分配!
\color{Red}{并未“真正”地被使用所以无法查出占用,但也无法被分配!}
并未“真正”地被使用所以无法查出占用,但也无法被分配!
排查动态端口占用
动态端口范围
动态端口是windows操作系统可以为客户端应用程序分配的临时端口。
查看动态端口范围的命令
# tcp协议,nacos基于tcp
netsh int ipv4 show dynamicportrange protocol=tcp
# udp协议
netsh int ipv4 show dynamicportrange protocol=udp
输出类似于
C:\Users\CC>netsh int ipv4 show dynamicportrange protocol=tcp
协议 tcp 动态端口范围
---------------------------------
启动端口 : 1024
端口数 : 13977
C:\Users\CC>netsh int ipv4 show dynamicportrange protocol=udp
协议 udp 动态端口范围
---------------------------------
启动端口 : 49152
端口数 : 16384
表示1024到15001,49152到65536之间的端口是可以被分配的。
属于动态端口范围,却无法分配即可能被“征用”了,例如规划给WSL
。即保留端口。
保留端口范围
查看保留端口范围:
# tcp协议
netsh interface ipv4 show excludedportrange protocol=tcp
# udp协议
netsh interface ipv4 show excludedportrange protocol=udp
# linux系统
sudo iptables -L --line-numbers -t filter -p tcp
可以看到报错被占用的端口号处于保留端口范围中,已破案。
C:\Users\CC>netsh interface ipv4 show excludedportrange protocol=tcp
协议 tcp 端口排除范围
开始端口 结束端口
---------- --------
2869 2869
8470 8569
8781 8880
13337 13436
13437 13536
50000 50059
C:\Users\CC>netsh interface ipv4 show excludedportrange protocol=udp
协议 udp 端口排除范围
开始端口 结束端口
---------- --------
50000 50059 *
55806 55905
60182 60281
61971 62070
62894 62993
64228 64327
64328 64427
动态端口占用解决
方案1:关闭应用
关闭Hyper-v
或WSL2
,最简单。
但是装这俩一般有使用docker需求,可以排除需要的端口,或修改动态端口范围。
方案2:排除端口
建议方案。排除指定的端口不被动态分配:
# windows 需要管理员权限。
# netsh int ipv4 add excludedportrange protocol=tcp startport=要排除的端口 numberofports=范围
netsh int ipv4 add excludedportrange protocol=tcp startport=8848 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=9848 numberofports=1
netsh int ipv4 add excludedportrange protocol=tcp startport=9849 numberofports=1
# linux
sudo iptables -A INPUT -p tcp --dport 8848:9849 -j DROP
若报错“另一个程序正在使用此文件”,需要先终止该程序。
使用下面两种方式停止Hyper-v或WSL之后, 重启 > 管理员打开powershell > 添加排除端口 > 重新启用Hyper-v或WSL > 再次重启即可
Hyper-v启停有关命令
#查看状态
Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All
#启用
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All
#禁用
Disable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Hypervisor
WSL启停
设置 > 系统(有的windows版本在【应用】中)>可选功能>更多widows功能 > 取消勾选【适用于Linux的Windows子系统】
事后重启。
方案3:设置保留端口范围
另一方案是重设保留端口的范围:
# ipv4 start表示起始端口号,num表示范围
netsh int ipv4 set dynamic tcp start=10000 num=13977
# ipv6
netsh int ipv6 set dynamic tcp start=10000 num=13977