前提

检查系统是否支持 WSL2: 选择 Windows 徽标键 + R,然后键入 “winver”

  • 对于 x64 系统:版本 1903 或更高版本,采用 内部版本 18362 或更高版本。
  • 对于 ARM64 系统:版本 2004 或更高版本,采用 内部版本 19041 或更高版本。
  • 低于 18362 的版本不支持 WSL 2。

开启 WSL

  • 首先需要使用管理员权限打开 PowerShell 执行如下命令

    1
    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  • 或者在程序和功能选打开 适用于 Linux 的 Windows 子系统 出现提示时,重启计算机。

开启 WSL2

  • 以管理员身份打开 PowerShell 并运行如下代码 启用虚拟机功能

    1
    dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
  • 重启计算机

  • 更新 wsl: 应用商店更新 或 Github 下载

    1
    Add-AppxPackage -Path F:\Microsoft.WSL_1.2.5.0_x64_ARM64.msixbundle
  • 安装 Linux 内核更新包,: 在浏览器中打开 https://aka.ms/wsl2kernel,下载适合你系统版本的 WSL 2 内核更新包,并安装该更新包。

  • 打开 PowerShell,然后在安装新的 Linux 发行版时运行以下命令,将 WSL 2 设置为默认版本

    1
    wsl --set-default-version 2

WSL 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 列出分发版
wsl -l
wsl --list --running
wsl -l -v # 查看子系统状态

# 将 WSL 2 设置为默认版本
wsl --set-default-version 2

# 设置默认分发版
wsl -s Ubuntu
wsl --set-version Ubuntu-20.04 1

# 立即终止所有正在运行的发行版和 WSL 2 轻量级实用程序虚拟机
wsl --shutdown

# 注销后,与该分发关联的所有数据、设置和软件都将永久丢失。 从 Store 重新安装会安装分发版的干净副本。
wsl --unregister <DistributionName>
wsl --unregister Ubuntu


# 用于管理适用于 Linux 的 Windows 子系统的参数
--export <分发版> <文件名> 将分发版导出到 tar 文件
--import <分发版> <安装位置> <文件名> 导入指定的 tar 文件作为新的分发版

systemd 支持

  • init: WSL2 的发行版均拥有微软提供的 init,它是一种 systemd 的替代方案,不支持 systemctl 命令,WSL2 本身是由 Windows 负责运行的,因此使用 tree 或 ps 命令时会看到根进程不是 systemd,这将导致无法启动 Linux 系统服务的守护进程 (deamon)。当我们执行 systemctl 命令的时候,会显示出我们的 init system (PID 1) 并非 systemd,而是微软提供的 init。

  • systemd:在较新的 Linux 系统上,都使用 systemd 管理进程,成为系统的第一个进程(PID 等于 1),其他进程都是它的子进程。systemd 为系统启动和管理提供了完整的解决方案。它提供了一组命令。字母 d 是守护进程(daemon)的缩写。

  • 打开 WSL2 终端,使用以下命令安装 systemd:

    1
    sudo yum install -y systemd
  • /etc 目录新建 wsl.conf 文件,添加如下内容:

    1
    sudo sh -c 'echo "[boot]\nsystemd=true" >> /etc/wsl.conf'
    1
    2
    [boot]
    systemd=true
  • 重启 WSL, 重新在 Windows Terminal 中打开 LInux 发行版,输入如下命令检查是否成功:

    1
    2
    wsl --shutdown
    systemctl

静态 IP 地址

  • windows 访问 wsl:使用 localhost 即可(但是不能使用 127.0.0.1)

  • windows 的 docker 不支持使用 host 网络,也就是不能通过 localhost 访问 wsl, ip 是可以的,但 wsl 的 ip 每次启动都会变,如果需要一个固定的 IP,需要做一些设置。

  • 查看 “vEthernet(WSL)” 的网络接口配置 IP 地址

    1
    netsh.exe interface ip show addresses "vEthernet (WSL)"
  • 设置 Windows 的 vEthernet (WSL) 网卡;假定 ip 为 192.168.233.1;

    1
    2
    3
    4
    5
    6
    7
    8
    # 删除 vEthernet(WSL)接口上所有的 IPv4  IPv6 地址 地址配置。
    Remove-NetIPAddress -InterfaceAlias "vEthernet (WSL)" -AddressFamily IPv4, IPv6
    # 添加一个名为 "vEthernet (WSL)" 的网络适配器并分配 IP 地址 "192.168.233.1 /24" 给它。
    New-NetIPAddress -IPAddress "192.168.233.1" -PrefixLength 24 -InterfaceAlias "vEthernet (WSL)"
    # 删除名为 "WSLNat" 的 NAT(网络地址转换)规则。
    Get-NetNat | Where-Object Name -Eq WSLNat | Remove-NetNat -Confirm:$False
    # 添加一个名为 "WSLNat" 的 NAT 规则,将 WSL 虚拟机的 IP 地址 “192.168.233.0/24” 映射到宿主机的网络适配器上。
    New-NetNat -Name WSLNat -InternalIPInterfaceAddressPrefix "192.168.233.0/24"
  • Linux 配置 : 在 WSL2 Linux ~/.bashrc 中添加下面脚本

    1
    2
    3
    4
    5
    6
    ip addr show eth0 | grep -s "192.168.233.2/24" > /dev/null
    if [ $? == 1 ]; then
    ip addr del $(ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | head -n 1) dev eth0
    ip addr add 192.168.233.2/24 broadcast 192.168.233.255 dev eth0
    ip route add 0.0.0.0/0 via 192.168.233.1 dev eth0
    fi
  • 配置 DNS, 在 /etc/wsl.conf 文件写入

    1
    2
    [network]
    generateResolvConf = false # 不自动生成dns配置
  • 删除 /etc/resolv.conf 的 nameserver,重新设置

    1
    2
    3
    4
    rm /etc/resolv.conf
    vim /etc/resolv.conf
    nameserver 114.114.114.114
    nameserver 180.76.76.76
  • win11 能够 ping 通 wsl2,但是 wsl2 无法 ping 通 win11, 经分析主要是 win11 防火墙的原因. 在 win11 中 执行如下命令 (管理员运行 powershell 或 cmd):

    1
    2
    3
    4
    New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow

    # 取消
    New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Block
  • 可以修改 C:\Windows\System32\drivers\etc\hosts

    1
    192.168.233.2	wsl2
  • 后续可以通过 wsl2 访问

WSL2 内存控制

笔记本一直没有关机,用任务管理器里面查看发现是 Vmmem 这个进程占用了大量的内存,这个就是 wsl 对应的虚拟机进程。目前来说主要有以下几个解决方案:

  • 重启 wsl2: 使用 wsl --shutdown 命令就可以关闭全部的 wsl2 虚拟机了。之后再随意打开一个 wsl2 的窗口就会再次开启虚拟机

  • 使用.wslconfig 文件限制资源:创建一个 %UserProfile%\.wslconfig 文件, 里面加入以下内容来限制 wsl2 的内存, 需要重启 wsl2 才能生效。

    1
    2
    3
    4
    5
    6
    [wsl2]
    processors=8
    memory=4GB
    swap=8GB
    #是否应可通过 localhost:port 从主机连接。
    localhostForwarding=true
  • 调整内核参数定期释放 cache 内存: Linux 内核中有一个参数 /proc/sys/vm/drop_caches,是可以用来手动释放 Linux 中的 cache 缓存,如果发现 wsl2 的 cache 过大影响到宿主机正常运行了,可以手动执行以下命令来释放 cache:

    1
    echo 3 > /proc/sys/vm/drop_caches
  • 查看内存

    1
    2
    3
    4
    # 查看内存、swap大小
    free -m
    # 查看处理器个数
    cat /proc/cpuinfo| grep "processor"| wc -l

设置默认登录用户

  • 使用 vim /etc/wsl.conf 进行配置,wsl.conf 配置优先级要高于 config --default-user,因此如果两个都配置了的话,会以 wsl.conf 中的配置优先。

    1
    2
    3
    [user]
    # 启动的默认用户
    default = root
  • 通过以下命令来指定进入 wsl 的时候使用的用户:

    1
    2
    # wsl -u <Username>,wsl --user <Username>
    wsl -u root
  • 如果希望修改默认用户的话,则需要进行设置

    1
    2
    # <DistributionName> config --default-user <Username>
    centos.exe config --default-user root
  • 注意在直接退出 wsl 之后配置并没有直接生效,而是在 wsl 重启之后才会生效,所以我们可以使用命令使 wsl 先关闭,然后再重新进入就会发现 hostname已经修改过来了。

    1
    2
    wsl --shutdown
    wsl

备份/迁移

  • 在 Windows PowerShell 中输入如下命令

    1
    2
    3
    4
    5
    6
    7
    PS C:\Users\dev> wsl -l --all -v
    NAME STATE VERSION
    * CentOS7 Running 2
    Ubuntu-20.04 Stopped 2
    docker-desktop-data Running 2
    docker-desktop Running 2
    PS C:\Users\dev> wsl --shutdown
  • 导出分发版为 tar 文件到 d 盘(如果你只是备份,那么下面的到第二步就可以了)

    1
    2
    wsl --export Ubuntu-20.04 d:\\wsl-ubuntu20.04.tar
    wsl --export CentOS7 d:\\wsl-CentOS7.tar
  • 注销当前分发版

    1
    2
    wsl --unregister Ubuntu-20.04
    wsl --unregister CentOS7
  • 重新导入并安装 WSL, 在 d:\wsl-ubuntu20.04(迁移/还原到其他目录)

    1
    2
    wsl --import Ubuntu-20.04 d:\\wsl\ubuntu20.04 d:\\wsl-ubuntu20.04.tar --version 2
    wsl --import CentOS7 d:\\wsl\CentOS7 d:\\wsl-CentOS7.tar --version 2
  • 删除 tar 文件(可选)

    1
    del d:\\wsl-ubuntu20.04.tar
  • 设置 wsl 版本

    1
    wsl --set-version Ubuntu-20.04 2

文件系统互通

  • 相比于 WSL1,这次增加了 Windows 访问 Linux 分区的能力,可以在资源管理器中输入 \\wsl$\<子系统名> 访问对应的子系统分区,为了方便也可以在资源管理器中把 Linux 分区挂载成一个磁盘。
  • WSL2 访问 Windows 文件系统依然通过挂载分区的方式,
  • Windows 下的磁盘会被挂载在 /mnt 下,例如 /mnt/c
  • 更加方便的一个方式是,在 Terminal 中,使用 explorer.exe . 可以直接调用资源管理器打开当前目录,有点类似 Mac 下的 open .

总结

在体系结构上 WSL2 没有太大的创新,本质就是一台跑在 Hyper-V 上的虚拟机,你可以使用 VMWare Workstation 或 VirtualBox,经过简单的配置实现其 100% 的功能,WSL2 是一项原生功能,其配置上的便利性和兼容性,大大减少了使用者花在配置上的精力,最大程度的实现开箱即用,使用 Windows + WSL2 来构建开发环境已经可以满足大部分的需求。