Windows下WSL的使用

 

安装步骤

安装WSL1

  1. 以管理员身份打开PowerShell并运行下面命令来开启Linux子系统功能
1
2
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

  1. 下载镜像并自动安装到默认位置
1
2
3
Invoke-WebRequest -Uri https://aka.ms/wsl-debian-gnulinux -OutFile Debian.Appx -UseBasicParsing
Add-AppxPackage .\Debian.Appx

  1. 也可以手动下载并自定义安装位置
1
2
3
4
5
6
7
curl.exe -L -o Debian.Appx https://aka.ms/wsl-debian-gnulinux
mv Debian.Appx Debian.zip
unzip Debian.zip

# 首次运行需要以管理员身份运行Debian文件夹下的debian.exe进行初始化
# 初始化完成后续可以普通用户运行debian.exe运行WSL

  1. 其他系统镜像下载地址

启用WSL2

  1. 在Win10 1903或更高版本中可启用WSL2

  2. 使用管理员权限通过执行如下命令打开【Linux子系统支持】及【启用虚拟平台功能】

1
2
3
4
5
6
7
8
# 在 命令提示符 中启用功能,跟PowerShell二选一执行即可
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# 在 PowerShell 中启用功能,跟命令提示符二选一执行即可
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

  1. 下载安装WSL2的Linux内核安装包,下面是部分使用命令,现在通过 wsl --install 已经可以自动安装了
1
2
3
4
5
6
wsl --list --verbose			# 查看已安装的Linux版本
wsl --set-default Debian # 设置 Debian为默认系统
wsl --set-default-version 2 # 将WSL 2设置为默认版本
wsl --set-version Debian 1 # 将Debian设置为WSL1版
wsl --set-version Ubuntu 2 # 将Ubuntu设置为WSL2版

  1. 可先设置好WSL的默认版本为1后再去商店安装Debian,然后再将默认版本改为WSL2后再去商店安装Ubuntu

迁移系统

  1. 导出系统并迁移根文件系统至D盘,管理员身份运行命令提示符
1
2
3
4
5
6
7
8
# 迁移不需要卸载及重装WSL,直接注销和导入即可。在配置好WSL2环境的情况下,可不安装Debian APP直接导入先前的备份
# 但是不安装Debian APP无法使用debian命令来设置默认登录用户且无图标
# wsl --export Debian E:\Debian.tar # 迁移前建议先备份当前WSL系统到其他位置

wsl --unregister Debian # 先注销当前WSL分发版
wsl --import Debian D:\Soft\Debian D:\Debian.tar --version 2 # 再迁移WSL到D盘
debian config --default-user leux # 最后切换默认登录用户

  1. 如果代理软件和wsl2的sock端口冲突,可使用netsh winsock reset临时重置修复
1
2
3
4
5
参考的对象类型不支持尝试的操作。
Press any key to continue...

netsh winsock reset

其他命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
wsl --status						# 查看当前默认发行版和版本
wsl --version # 查看WSL组件版本
wsl --update # 更新WSL组件版本
wsl --shutdown # 终止所有正在运行的发行版
wsl --unregister <DistroName> # 注销并卸载WSL发行版
wsl --terminate <DistroName> # 终止指定的发行版或阻止其运行

wsl --list --online # 查看可用发行版列表
wsl --list --verbose # 列出已安装的发行版
wsl --install <DistroName> # 安装指定的发行版
wsl --set-default-version <Version> # 设置默认 WSL 版本
wsl --set-default <DistroName> # 设置默认 Linux 发行版
wsl --set-version <DistroName> 2 # 将发行版设置为使用WSL2
wsl --install --no-distribution # 安装 WSL 时不安装发行版

# 导入导出指定发行版为tar文件,参数:--vhd:指定导出分发版应为 .vhdx 文件而不是 tar 文件(这仅在使用 WSL 2 的情况下受支持)
wsl --export <DistroName> <FileName> # 导出为新的分发文件
wsl --import <DistroName> <InstallLocation> <FileName> # 导入,--version <1/2>:指定将分发版导入为 WSL 1 还是 WSL 2 分发版

# 通过PowerShell或CMD运行特定的Linux发行版,用户必须存在(例如root)
wsl --distribution <DistroName> --user <UserName>

# 更改发行版登录的默认用户,该用户必须已经存在,例如:debian.exe config --default-user leux
<DistroName> config --default-user <Username>

编译内核

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 除了使用官方内核外,还可以自己编译添加了更多功能的内核,首先查看当前使用的官方内核版本
Linux B650I 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 GNU/Linux

# 官方WSL2内核源码及分支版本:https://github.com/microsoft/WSL2-Linux-Kernel
linux-msft-wsl-6.6.y linux-msft-wsl-6.1.y linux-msft-wsl-5.15.y
linux-msft-wsl-5.10.y linux-msft-wsl-5.4.y linux-msft-wsl-4.19.y

# 安装编译所需依赖
sudo apt install build-essential flex bison libssl-dev libelf-dev flex bison bc dwarves rsync

# 获取官方WSL2内核源码,以最新的 linux-msft-wsl-6.6.y 为例
git clone --depth=1 -b linux-msft-wsl-6.6.y https://github.com/microsoft/WSL2-Linux-Kernel

# 开始编译WSL内核
cd WSL2-Linux-Kernel/
#make menuconfig KCONFIG_CONFIG=Microsoft/config-wsl # 可选使用官方内核配置,打开 WSL2 内核配置界面
make -j$(nproc) KCONFIG_CONFIG=Microsoft/config-wsl # 构建 WSL2 自定内核,内核配置 Microsoft/config-wsl 指向 arch/x86/configs/config-wsl
cp arch/x86/boot/bzImage /mnt/c/'Program Files'/WSL/tools/ # 拷贝内核到指定位置,当模块都内置时可用

# 分别安装内核,模块,头文件到指定路径待用
mkdir -p ${HOME}/kernel/boot ${HOME}/kernel/usr # 若 INSTALL_PATH 不存在会报错路径不存在
make install INSTALL_PATH=${HOME}/kernel/boot # 内核:~/kernel/boot/vmlinuz-* 符号表:~/kernel/boot/System.map-*
make modules_install INSTALL_MOD_PATH=${HOME}/kernel # 模块安装路径:~/kernel/lib/modules/*
make headers_install INSTALL_HDR_PATH=${HOME}/kernel/usr # 头文件安装路径:~/kernel/usr/include/*

cp ${HOME}/kernel/boot/vmlinuz-6.6.75.1-LEUX-WSL2 /mnt/c/'Program Files'/WSL/tools/ # 也可选择拷贝安装后的内核到指定位置
sudo cp -r ${HOME}/kernel/lib/modules/6.6.75.1-LEUX-WSL2/ /lib/modules/ # 拷贝模块到指定位置,注意备份删除原来的

# WSL 旧版本的默认内核位于:C:\Windows\System32\lxss\tools\kernel
# WSL2新版本的默认内核位于:C:\Program Files\WSL\tools\kernel # 默认模块目录位于:C:\Program Files\WSL\modules
# WSL2版本下的系统镜像位于:C:\Users\leux\AppData\Local\Packages\<DistroPackageName>\LocalState\ext4.vhdx

打包模块

  1. 使用内核源码中提供的脚本自动将模块打包成VHDX镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
# 编译内核后安装模块到指定路径后通过脚本打包成VHDX镜像
make -j$(nproc) KCONFIG_CONFIG=Microsoft/config-wsl
make INSTALL_MOD_PATH="$PWD/modules" modules_install
sudo ./Microsoft/scripts/gen_modules_vhdx.sh "$PWD/modules/lib/modules/6.6.75.1-LEUX-WSL2/" modules.vhdx

# 脚本会把模块安装目录 lib/modules/6.6.75.1-***/ 下的所有文件如 kernel/ modules.alias modules.dep 等打包入 modules.vhdx 中
# 而 WSL2 会在发行版的 /lib/modules/ 下创建目录 6.6.75.1-*** 并把 modules.vhdx 镜像挂载到此,即使换到其他vhdx后该空目录也不会删除

B650I:~# uname -a
Linux B650I 6.6.75.1--LEUX-WSL2 #1 SMP PREEMPT_DYNAMIC Sat Feb 8 02:00:20 UTC 2025 x86_64 Linux
B650I:~# mount | grep modules
none on /lib/modules/6.6.75.1-LEUX-WSL2 type overlay (rw,nosuid,nodev,noatime,lowerdir=/modules,upperdir=/lib/modules/6.6.75.1-LEUX-WSL2/rw/upper,workdir=/lib/modules/6.6.75.1-LEUX-WSL2/rw/work,uuid=on)

  1. 也可手动执行下面命令来生成模块VHDX镜像(下面的内容便是上面脚本中要执行的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 指定内核安装后内容所在的路径
KERNEL_PATH=/home/leux/kernel/lib/modules/6.6.75.1-LEUX-WSL2

# 计算安装模块所在的目录总大小(modules_size + 268435456)
modules_size=$(du -bs "$KERNEL_PATH" | awk '{print $1;}')
modules_size=$((modules_size + (256*(1<<20))))

# 创建一个存放模块的空白镜像文件
dd if=/dev/zero of="$PWD/modules.img" bs=1024 count=$((modules_size / 1024))

# 设置文件系统并挂载镜像文件
lo_dev=$(sudo losetup --find --show "$PWD/modules.img")
sudo mkfs -t ext4 "$lo_dev"
mkdir "$PWD/modules_img"
sudo mount "$lo_dev" "$PWD/modules_img"
sudo chmod a+rw "$PWD/modules_img"

# 复制模块到镜像中,完成后卸载镜像
cp -r "$KERNEL_PATH"/* "$PWD/modules_img"
sudo umount "$PWD/modules_img"

# 将img镜像转换为VHDX
qemu-img convert -O vhdx "$PWD/modules.img" "$PWD/modules.vhdx"

  1. 在配置文件中指定内核及VHDX模块的路径
1
2
3
4
5
6
7
8
9
10
# WSL2应用将从 2.5.1 才开始支持选择模块作为VHD分发【Update Kernel to 6.6.75 and switch modules to a vhd】
# WSL2内核版本 6.6.y 中提供将内核模块打包为VHD/VHDX镜像的脚本:https://github.com/microsoft/WSL/issues/12586
# https://github.com/microsoft/WSL/releases/download/2.5.1/wsl.2.5.1.0.x64.msi
# https://github.com/microsoft/WSL2-Linux-Kernel/blob/linux-msft-wsl-6.6.y/Microsoft/scripts/gen_modules_vhdx.sh

# 然后在配置文件 %USERPROFILE%\.wslconfig 中指定内核及VHDX模块的路径
[wsl2]
kernel=C:\\Program Files\\WSL\\tools\\vmlinuz-6.6.75.1-LEUX-WSL2
kernelModules=C:\\Program Files\\WSL\\tools\\leux-modules.vhdx

构建系统

  1. 除了使用官方提供的系统外,也可直接使用别人构建好的WSL2系统
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
a. 下载打包好的WSL2系统:https://github.com/yuk7/AlpineWSL/releases/download/3.21.3-0/Alpine.zip
b. 将该 Alpine.zip 包中仅含的 Alpine.exe 和 rootfs.tar.gz 文件解压到同一目录
c. 运行 Alpine.exe 会自动提取 rootfs.tar.gz 并注册到 WSL,WSL2会在当前目录下生成 ext4.vhdx

# Alpine.exe 用于注册的实例名称,如果重命名它再运行可以使用其他名称注册实例来进行多次安装
# 例如:如果要将 "Arch" 用作实例名称,请重命名为 Arch.exe 实例名称中不能有空格

# 在文件 https://github.com/yuk7/wsldl/blob/main/src/install/install.go 中定义了默认rootfs的文件名
defaultRootFiles = []string{
"install.tar",
"install.tar.gz",
"install.tgz",
"install.tar.zst",
"install.tar.xz",
"rootfs.tar",
"rootfs.tar.gz",
"rootfs.tgz",
"rootfs.tar.zst",
"rootfs.tar.xz",
"install.ext4.vhdx",
"install.ext4.vhdx.gz",
}

  1. 还可以自己手动构建WSL2系统,主要依赖这个高级WSL系统安装和启动程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 直接用Alpine和Ubuntu官方的rootfs制作WSL镜像
mkdir Ubuntu && cd Ubuntu
wget -O Ubuntu.exe https://github.com/yuk7/wsldl/releases/download/25030400/wsldl.exe
wget -O rootfs.tar.gz http://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/ubuntu-base-24.04.2-base-amd64.tar.gz

mkdir Alpine && cd Alpine
wget -O Alpine.exe https://github.com/yuk7/wsldl/releases/download/25030400/wsldl.exe
wget -O rootfs.tar.gz https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.21.3-x86_64.tar.gz

PS C:\Soft\Alpine> .\Alpine.exe
Using: C:\Soft\Alpine\rootfs.tar.gz
Installing...
Installation complete
Press enter to continue...
PS C:\Soft\Alpine>


# Alpine用官方的rootfs手动调整后制作WSL镜像
wget https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.21.3-x86_64.tar.gz
mkdir rootfs
sudo tar -zxpf alpine-minirootfs-3.21.3-x86_64.tar.gz -C rootfs
sudo cp -f /etc/resolv.conf rootfs/etc/resolv.conf
sudo cp -f profile rootfs/etc/profile
sudo chroot rootfs /sbin/apk update
sudo chroot rootfs /sbin/apk add bash
echo "# This file was automatically generated by WSL. To stop automatic generation of this file, remove this line." | sudo tee rootfs/etc/resolv.conf
sudo rm -rf `sudo find rootfs/var/cache/apk/ -type f`
sudo chmod +x rootfs

cd rootfs
sudo tar -zcpf ../rootfs.tar.gz `sudo ls`
sudo chown `id -un` rootfs.tar.gz

  1. 上面那个GO写的 wsldl.exe 程序的一些用法
1
2
3
4
5
6
7
8
9
10
11
12
# 使用任何 install.tar(.gz),install.ext4.vhdx(.gz) 磁盘映像进行安装(仅限 WSL2)
wsldl.exe clean # 如何卸载实例
wsldl.exe config --default-user user # 更改默认用户
wsldl.exe backup backup.tar.gz # 导出到 backup.tar.gz(WSL1 或 2)
wsldl.exe backup backup.ext4.vhdx.gz # 导出到 backup.ext4.vhdx.gz(仅限 WSL2)
wsldl.exe install backup.tar.gz # 如何导入.tar(.gz) (WSL1 或 2)
wsldl.exe install backup.ext4.vhdx.gz # 如何导入.ext4.vhdx(.gz)(仅限 WSL2)

# 导入导出指定发行版为tar文件,参数:--vhd:指定导出分发版应为 .vhdx 文件而不是 tar 文件(这仅在使用 WSL 2 的情况下受支持)
wsl --export <DistroName> <FileName> # 导出为新的分发文件
wsl --import <DistroName> <InstallLocation> <FileName> # 导入,--version <1/2>:指定将分发版导入为 WSL 1 还是 WSL 2 分发版

配置文件

  1. 现在 WSL2 和 Windows 主机的网络互通而且 IP 地址相同还支持了 IPv6 ,并且从外部可以同时访问 WSL2 和 Windows 的网络。并且 Windows 防火墙也能过滤 WSL 里的包了,再也不需要什么桥接网卡、端口转发之类的操作了。

  2. 既可安装Microsoft Store中的WSL,然后打开应用 WSL Settings 来通过GUI配置,也可手动修改配置文件来更改

  3. 局部配置:仅在当前 WSL1 或 WSL2 系统生效的配置文件在发行版内的 /etc/wsl.conf

  4. 全局配置:仅在 WSL2 上所有已安装发行版的全局设置在Windows中的 %USERPROFILE%\.wslconfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 例如以全局配置 C:\Users\leux\.wslconfig 为例
[wsl2]
kernel=C:\\Program Files\\WSL\\tools\\bzImage
autoProxy=false # 是否强制 WSL2/WSLg 子系统使用 Windows 代理设置(请根据实际需要启用)
dnsTunneling=true # WSL2/WSLg DNS 代理隧道,以便由 Windows 代理转发 DNS 请求(请根据实际需要启用)
firewall=true # WSL2/WSLg 子系统的 Windows 防火墙集成,以便 Hyper-V 或者 WPF 能过滤子系统流量(请根据实际需要启用)
guiApplications=true # 启用 WSLg GUI 图形化程序支持
ipv6=true # 启用 IPv6 网络支持
localhostForwarding=true # 启用 localhost 网络转发支持
memory=4GB # 限制 WSL2/WSLg 子系统的最大内存占用
nestedVirtualization=true # 启用 WSL2/WSLg 子系统嵌套虚拟化功能支持
networkingMode=mirrored # 启用镜像网络特性支持
# pageReporting=true # 启用 WSL2/WSLg 子系统页面文件通报,以便 Windows 回收已分配但未使用的内存
processors=8 # 设置 WSL2/WSLg 子系统的逻辑 CPU 核心数为 8(最大肯定没法超过硬件的物理逻辑核心数)
vmIdleTimeout=-1 # WSL2 VM 实例空闲超时关闭时间,-1 为永不关闭,根据参数说明,目前似乎仅适用于 Win11+

[experimental] # 实验性功能(按照过往经验,若后续转正,则是配置在上面的 [wsl2] 选节)
autoMemoryReclaim=gradual # 启用空闲内存自动缓慢回收,其它选项:dropcache / disabled(立即/禁用)
hostAddressLoopback=true # 启用 WSL2/WSLg 子系统和 Windows 宿主之间的本地回环互通支持
sparseVhd=true # 启用 WSL2/WSLg 子系统虚拟硬盘空间自动回收
useWindowsDnsCache=false # 和 dnsTunneling 配合使用,决定是否使用 Windows DNS 缓存池

[interop] # Linux 和 Windows 的互操作设置
enabled = false # WSL中是否支持启动 Windows 进程
appendWindowsPath = false # 是否将 Windows 的环境变量 %PATH% 添加到 Linux 的环境变量 $PATH

压缩VHDX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# WSL2创建的VHDX默认使用ext4文件类型且容量上限为1TB,但由于虚拟磁盘大小是只增不减的,现将其压缩瘦身到实际占用大小
wsl --shutdown # 首先关闭WSL2系统
diskpart # 然后在该命令交互界面中执行如下

diskpart> select vdisk file="C:\Users\leux\AppData\Local\wsl\{bdd8a417-4726-4b49-ac94-d07f119a9f77}\ext4.vhdx" # 选择虚拟磁盘文件
diskpart> attach vdisk readonly # 只读装载磁盘
diskpart> compact vdisk # 压缩虚拟磁盘
diskpart> detach vdisk # 分离虚拟磁盘
diskpart> exit # 退出磁盘管理

# 压缩前:7.68 GB (8,256,487,424 字节) --> 压缩后:5.71 GB (6,140,461,056 字节)

# 通过 wsl --install Debian 安装的系统镜像在目录 %LOCALAPPDATA%\wsl\{bdd8a417-4726-4b49-ac94-d07f119a9f77}\ext4.vhdx
# 通过 MicroSoft Store 安装的系统镜像在目录 %LOCALAPPDATA%\Packages\<Distro_Package_Name>\LocalState\ext4.vhdx

# 某些高版本的系统也可通过安装模块后执行指定命令进行磁盘缩减(未测试)
PS C:\Users\leux> Install-Module -Name Optimize-VirtualDisk
PS C:\Users\leux> Optimize-VHD -Path .\ext4.vhdx -Mode full

挂载硬盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# https://learn.microsoft.com/zh-cn/windows/wsl/wsl2-mount-disk
# 列出 Windows 中的可用磁盘,要用管理员执行,只能挂载磁盘而不能挂载USB或SD Card
PS C:\Users\leux> GET-CimInstance -query "SELECT * from Win32_DiskDrive"
DeviceID Caption Partitions Size Model
-------- ------- ---------- ---- -----
\\.\PHYSICALDRIVE0 KIOXIA-EXCERIA SSD 2 500105249280 KIOXIA-EXCERIA SSD
\\.\PHYSICALDRIVE1 KIOXIA-EXCERIA G2 SSD 3 1000202273280 KIOXIA-EXCERIA G2 SSD

# 将整个磁盘装载为单个卷(即如果磁盘未分区),则可以省略 --partition。
PS C:\Users\leux> wsl --mount \\.\PHYSICALDRIVE0 --partition 1 --type ext4
已成功将磁盘装载为“/mnt/wsl/PHYSICALDRIVE0p1”。
注意: 如果修改了 /etc/wsl.conf 中的 automount.root 设置,则位置会有所不同。
若要卸载和分离磁盘,请运行“wsl.exe --unmount \\.\PHYSICALDRIVE0”。

# 卸载和分离磁盘
PS C:\Users\leux> wsl.exe --unmount \\.\PHYSICALDRIVE0
操作成功完成。

# 最后进入WSL2中查看磁盘情况
leux@B650I:~$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sdd
├─sdd1 ext4 1.0 57fc3b80-f6be-4775-8b5c-fa6ba9af028d 70.1G 47% /mnt/wsl/PHYSICALDRIVE0p1
└─sdd2 ntfs Other 7008C4DB08C4A208

其他说明

  1. WSL需要运行Windows的版本要大于或等于16215版本,WSL2需要18362或更高版本,某些新特性仅在更高的系统版本上支持

  2. 启用相关组件后必须根据提示重启,WSL2须额外安装微软提供的WSL2内核,Linux子系统仅在系统驱动器上运行(通常是您的C:驱动器)

  3. 在WSL中运行Windows程序也可这样开关 echo 0 > /proc/sys/fs/binfmt_misc/WSLInterop 0 禁用,1 启用,重启失效

  4. WSL2-Linux-Kernel/scripts/setlocalversion 中第208行 echo "${KERNELVERSION}${file_localversion}${config_localversion}${LOCALVERSION}${scm_version}" 中的 ${scm_version} 删除即可去除内核版本后的+号