发布于 

用 Windows 开发遇到的各种问题

自从之前那段实习结束之后,我的日常开发就转变成了 Windows 10 + WSL2 的方式。刚开始的时候还觉得特爽,等新鲜感过去,这种模式成为常态之后, Windows 以及 WSL2 的各种毛病都逐渐涌现了出来。为了防止我之后再次遇到又变得一筹莫展,我将在这个文章里记录我使用 Windows 10 开发所遇到的各种问题(大概是会持续更新的……)。

Windows 侧端口被占用的问题

问题发现

起因是我有一天早上起来运行我的一个 React 前端项目,然后发现使用 yarn start 执行预设定好的启动脚本启动项目一直失败,报错 5555 端口被占用,重启电脑仍无法解决。这个 5555 端口并不是我自己某个设定中的端口,我觉得应该是我用的某个第三方模组,或者 Node 自生需要的端口,所以我没办法直接更改相关硬编码,只有寻求问题根本所在。

问题原理与解决办法

WSL2 是依托于 Hyper-V 进行虚拟化的,而这次的问题就处在 Hyper-V 上。在 Windows 启动后,Hyper-V 会预留几个范围的端口以便后续使用,而这次我就遇到了它将我需要用的 5555 端口占用了。通过以下指令可以查看被占用的端口范围:

1
netsh interface ipv4 show excludedportrange protocol=tcp

会得到像下面这样类似的输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
协议 tcp 端口排除范围

开始端口 结束端口
---------- --------
50000 50059 *
60767 60866
60967 61066
61067 61166
61167 61266
61267 61366
61367 61466
61855 61954
64121 64220

* - 管理的端口排除。

所以的这里的解决办法就是不断地重启系统直至需要的端口不被预留占用为止。

上面的端口排除通常是由 Windows NAT Driver 操作的,所以可以通过关闭它来清除端口占用,然后再重启。

1
2
net stop winnat
net start winnat

参考

WSL2 无法访问局域网 IP 以及互联网

问题发现

今天早上起来打开 WSL2 并使用 VSCode 的 Leetcode 插件准备水道题的,然后发现题怎么样都拉不下来,一直超时,然后发现原来是“断网了”。具体症状表现为:Windows 宿主机可以 ping 通 WSL2,WSL2 无法 ping 通 Windows 宿主机、无法 ping 通局域网中的虚拟机、无法 ping 同互联网上的域名与 IP,重启 WSL2 与 Windows 都无法解决这个问题。一开始以为是 Windows 防火墙的问题,然后给 Windows 的防火墙加了一条入站策略,发现可以 ping 通宿主机了,但是还是无法连接其他 IP 与域名,(我觉得 Windows 防火墙应该也不会妨碍 WSL2 访问外网吧?),所以应该不是防火墙的问题。我又检查了 ip route 与 DNS 发现都是正常的。

然后我尝试平时挂代理的方式把 http 和 https 代理到了 Windows 宿主机上,发现是可以请求到外网的数据的。但这并不是一个长久之计,而且只能走 http 请求明显无法满足我的需求。

然后我东搜西找终于在 GitHub 上找到了下面的这条奇葩方法。

问题原理与解决办法

这个问题的原理我目前还不知道,不知道会不会和我前一天重启了 Windows NAT Driver 有关,如果有人知道了可以通过我的邮箱或者其他 SNS 联系我(如果有人看到了的我这篇文章的话……)。

解决办法是到 控制面板->硬件和声音->电源选项->系统设置 里把 启用快速启动 取消勾选,然后重启电脑,然后就可以正常上网了,没错,就是这么简单……

能找到这个解决办法的老哥真的是个神人……希望微软之后能修复这个 bug 吧……

参考

WSL2 网络代理

现在的大陆的网络环境害的我们不得不掌握科学上网的技能,又是 WSL2 虚拟化的缘故,当使用科学上网工具进行系统代理时没法将 WSL2 侧的网络也给代理了,于是需要做一些特殊的操作。关于这个的文章网上其实有很多,我这里就简单的记录以下。

解决办法就是把请求代理(我就只做了 http 与 https 的,其他协议的咱也不知道怎么弄)到 Windows 宿主机这边的科学上网工具的端口上。

1
2
3
4
5
6
7
8
9
10
#!bin/bash
# WSL2 局域网的宿主机 IP
host_ip=$(cat /etc/resolv.conf |grep "nameserver" |cut -f 2 -d " ")
protocol=科学上网工具使用的协议
port=科学上网工具的本地监听端口
export http_proxy="$protocol://$host_ip:$port"
export https_proxy="$protocol://$host_ip:$port"
# 取消代理
# unset http_proxy
# unset https_proxy

可以把这个写成一个脚本放在某个地方,然后每次要用的时候就执行一下就行了,相应的可以再写一个取消代理的脚本。不过有一点要注意的就是,使用 sh 执行是会新开一个 shell 来执行的,这样环境变量并没有加载到当前 shell 上,还是無駄的,所以应该用 source 来执行。

另外值得说的一点是,/etc/resolv.conf 这个文件是 WSL 自动生成的,里面记录 DNS 的地址,在 WSL2 里就是宿主机的 IP,所以可以通过提取这个文件的内容然后在进行一些简单的文本操作就能拿到宿主机 IP。整个文件的内容类似下面这样:

1
2
3
4
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.31.208.1

看看微软之后还能给我整些什么活

看看微软之后还能给我整些什么活……