滚进 wsl2

2019年11月6日 · 1502 字 · 3 分钟 · Windows Wsl

本文已于 2020/05/26 更新,过时的信息已用删除线标注。

我是真没想到这都快过半年了 20H1 还没释出稳定版

早在今年上半年的 Build 2019 上,微软宣布了 wsl2,使得 wsl 不再只是 system call 的翻译,而是切切实实跑在一个真正的 Linux 内核之上。这样一来,wsl 将不再受内核的局限,能够运行 docker 等与 Linux kernel 密切相关的软件。

自宣布以来,wsl2 的开发很快提上日程,并将在 Windows 10 20H1 版本中可用。但想要升级至此版本,目前还需进入预览体验计划,而 Windows 10 目前的 bug 数量使我对 insider fast ring 望而却步。 最近在经过了很长时间的心理斗争之后,我最终还是进入了快速预览版,开始体验 wsl2,下面是途中遇到的一些坑,留存至此,以备后来者避坑。

首先需要说明的是,wsl1 与 wsl2 各有优劣,两者之间并非常规意义上的「升级」,更像是一种并行。如果并非是涉及内核等问题,仅仅是执行一些上层程序,我个人建议继续使用 wsl1,这样更加节省内存等资源。(当然可以 wsl1 与 wsl2 各安装一个/多个,按需启动)

安装

安装过程参考官方的 WSL 2 的安装说明 即可。

首先滚入 20H1 的预览版,升级系统,而后开启 hyper-v 平台,跑一个命令将原本的 wsl1 转为 wsl2 即可。更改的过程可能要花几分钟时间,等待就好。

之后就能开始使用 wsl2 啦!

各种坑

……当然,路途不总是一帆风顺的,而是伴随着艰难险阻。

虚拟机

由于 VMware 暂未支持嵌套虚拟化,所以开启了 hyper-v 之后,将无法继续使用 VMware 虚拟机。虽然 hyper-v 本身也能装个虚拟机应个急,但体验确实是远远不如 VMware 的。

VMware 20H1 技术预览版已支持嵌套虚拟化,可以与 hyper-v 共存,更多信息与下载链接等请 点击此处

terminal

另外就是终端问题了。

我在 wsl1 时期一直使用的终端 wsl-terminal 由于很久没有更新,所以并没有支持 wsl2,但见鬼的是我升级完之后 wsl1 也没办法用了……不过好在还有 windows terminal 这个官方的终端可以使用(虽然现在还不能输入中文有点难受)。

有一个方法则是可以先启动 powershell,然后通过命令行启动 wsl2。

wsl-terminalwsl-tty 均已支持 wsl2。但由于 windows terminal 的卓越体验(现已支持中文输入),我更为推荐使用 windows terminal 作为 wsl 的终端。感兴趣的可以参考一下 我的 windows terminal 配置

代理

安装了 hyper-v 之后,会将一系列端口划入保留端口之中,其中就包括了某软件的默认端口 1080。解决方法也很简单,换一个高位端口即可。(各种配置里的更改就是一项大工程了)

但真正吊诡则是,在我最初试用 hyper-v 时并未出现这个情况,开始使用 wsl2 后才发生……

此外,wsl2 与 windows 之间存在着网络隔离,虽然 wsl 团队已全力优化但还存在着一些可能会影响体验的问题。如在 windows 中可用 localhost 直接访问 wsl2 的 localhost,但反之则不行。

如果想要在 wsl 中利用 windows 本身的代理,可以在 ~/.zshrc~/.bashrc 中写入以下配置(我并不熟悉 fish 所以请 fish 用户自己改改吧):

# wsl 2 中请启用下面这一行
# export hostip=$(cat /etc/resolv.conf | grep -oP '(?<=nameserver\ ).*')
# wsl 1 中请启用下面这一行
# export hostip="127.0.0.1"
# 请将 1080 换为自己代理软件的端口
alias socks="http_proxy=http://${hostip}:1080 https_proxy=http://${hostip}:1080 "

source ~/.zshrc 之后即可通过 socks command params 来在 shell 中临时使用代理。

systemd

警告:作者本人已不在 wsl 2 中使用 docker 与 genie,本部分可能存在不可预知的错误,请审慎阅读。

由于 wsl2 的第一个(PID=1)进程是维持 windows 与 wsl2 通信等所需的 init,因此 systemd 无法以 PID=1 启动,直接无法使用。

但是,人民群众造轮子的热情是不可磨灭的(误),我们可以用 genie 来使用 systemd。

genie 的安装过程不再赘述,紧随官方文档或者使用 aur 即可。需要注意的是,genie 需要 dotnet 被引入环境变量,只需在你正使用的 shell 的配置文件(如 zsh 的 ~/.zshrc )中加入 export DOTNET_ROOT=/opt/dotnetsource 之以应用即可。

此外,由于其实现原理,最好将宿主机上自定义的 hosts 文件清空,以防出现问题。

安装成功之后,只需执行 genie -s ,systemd 即可正常使用。

docker

在 systemd 这一问题解决之后,docker 的安装与使用非常简单。

yay docker 安装之后,只需通过 systemctl 启用其服务即可,换源等不再赘述。

after

其实在这一套安装下来之后,甚至感觉有点没啥用(?