Win搭建:WSL2

12/31/2024 运维操作系统Windows

目录


参考:


# Win搭建:WSL2

WSL官方文档 (opens new window)

# 环境依赖

软件/系统 版本 架构 包名 备注
Windows 11 x86_64 CentOS 7.9-2211 (opens new window) WSL-CentOS
wsl_update_x64.msi (opens new window)
distrod_wsl_launcher-x86_64.zip (opens new window) wsl-distrod (opens new window)
# 查看系统版本号命令
winver
1
2

# 开启 WSL2 服务

打开控制面板 > 程序 > 程序和功能 > 启动或关闭Windows功能,勾选相关虚拟机的设置,点击确定后,等待安装完成后重新启动。

# 检测WSL环境

# 检查 WSL 状态
wsl --status 
1
2

若默认版本不是 2 ,则设置默认版本为2

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

# WSL常用命令

# 检查 WSL 状态
wsl --status 
# 列出已安装的 Linux 发行版
wsl -l -v 
# 进入默认的发行版本,退出执行 exit
wsl 
# 终止指定的发行版或阻止其运行,例:wsl --terminate Ubuntu-18.04
wsl --terminate xxx
# 重启wsl服务
wsl --shutdown
# 设置默认 Linux 发行版
wsl --set-default 
# 将WSL版本设置为1或2
wsl --set-version 
# 设置默认 WSL 版本,例:wsl --set-default-version 2
wsl --set-default-version 
# 运行特定的Linux发行版
wsl --distribution --user 
# 以特定用户的身份运行
wsl -u , wsl --user 
# 更改发行版的默认用户
wsl config --default-user
# 注销或卸载 Linux 发行版
wsl --unregister
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

实时显示时间和 IP 信息

watch -n1 -t -c 'echo -e "Running ...\n\e[1;32m时间: $(date +"%Y-%m-%d %H:%M:%S")\n\e[1;34mWSL IP: $(hostname -I 2>/dev/null | awk "{print \$1}")\n\e[1;33mHost IP: $(grep nameserver /etc/resolv.conf | awk "{print \$2}" | head -1)\e[0m"'
1

命令参数说明:

  • -n1:每秒刷新一次
  • -t:不显示顶部标题栏
  • -c:启用颜色支持

命令输出内容:

  • 绿色显示当前时间
  • 蓝色显示WSL的IP地址(使用 hostname -I 获取)
  • 黄色显示主机(Host)的IP地址(从 /etc/resolv.conf 获取)
  • 按 Ctrl+C 可退出监控。

# 安装 CentOS 系统

使用如下命令可查看官方在线的发行版

# 查看官方在线的发行版
wsl --list --online
1
2

官方没有提供CentOS7,可以从Github仓库下载,选择对用的版本下载:CentOS 7.9-2211 (opens new window)

下载完成后,解压是两个文件,如下:

双击CentOS7.exe即可安装,第一次安装可能会报错,需要先升级内核,下载wsl_update_x64.msi (opens new window)文件安装即可。

注意:在哪个目录下安装,则会在对应的目录下创建ext4.vhdx虚拟磁盘,不建议放到C盘,这个文件随着时间增长会变得很大,建议拷贝到其他指定目录下执行安装。

执行以下命令查看 CentOS 状态

# 列出已安装的 Linux 发行版
wsl -l -v 
1
2

执行一下命令进入默认的(*)的发行版本

# 进入默认的发行版本,退出执行 exit
wsl 
1
2

# 配置局域网SSH访问

image-20250321142235565

# 安装配置SSH

CentOS配置:远程登陆【ssh】

# Win端口转发

# 镜像网络模式

镜像网络模式,无需转发端口

# NAT网络模式

WSL的默认网络模式是NAT,在此模式下其他设备需要通过主机端口转发访问WSL应用。

WSL的对应的IP及应用端口映射到宿主Win对应的端口,命令如下(以管理员身份运行):

netsh interface portproxy add v4tov4 listenport=[Win端口] listenaddress=0.0.0.0 connectport=[WSL中应用端口] connectaddress=[WSL的IP]
1

检测是否设置成功

netsh interface portproxy show all
1
  • 参数解析:

    • netsh interface portproxy add v4tov4:添加 IPv4 到 IPv4 的端口代理规则。

    • listenport=[Win端口]:指定 Windows 主机监听的端口。

    • listenaddress=0.0.0.0:监听所有网络接口(允许外部设备通过任何接口访问)。

    • connectport=[WSL中应用端口]:指定目标端口(WSL 中应用的端口)。

    • connectaddress=[WSL的IP]:指定目标地址(WSL 的 IP,通常为 wsl hostname -I 获取的 WSL 内部 IP)。

# Win防火墙放行

在Win主机的防火墙开放对应端口,命令如下(以管理员身份运行):

New-NetFirewallRule -DisplayName "Allow SSH on Port 22" -Direction Inbound -Protocol TCP -LocalPort [指定端口] -Action Allow
1
  • 参数解析:

    • -DisplayName:定义规则的名称,显示在防火墙规则列表中。

    • -Direction Inbound:指定规则方向为入站(允许外部设备访问本机)。

    • -Protocol TCP:限制协议类型为 TCP。

    • -LocalPort [指定端口]:绑定到本机的端口。

    • -Action Allow:定义匹配流量时的动作(允许通过)。

  • 其他命令:

    • 查看所有入站规则

      Get-NetFirewallRule -Direction Inbound
      
      1
    • 按名称筛选规则

      Get-NetFirewallRule -DisplayName "Allow SSH*"
      
      1
    • 按端口筛选规则

      Get-NetFirewallRule -LocalPort 22,80,443
      
      1
    • 删除指定规则

      Remove-NetFirewallRule -DisplayName "Allow SSH on Port 22"
      
      1

# 常见问题

# 一、开机自启动问题

启动过程如下: Win开机 >> 执行Win开机脚本 >> 执行WSL系统脚本 >> 启动Linux程序

# Win开机脚本

原理:使用vb脚本,在Windows开机时执行,运行wsl,并隐藏wsl窗口。

操作:

  1. 快捷键Win+R,输入shell:startup,打开开机启动的程序目录。

    image-20250214150735904

  2. 在弹出的目录下,新建文本文件并修改文件名为wsl-startup.vbs,编辑文件vb脚本如下:

    rem 消息框
    Msgbox "开机自动启动wsl"
    rem 创建Wscript.Shell对象
    Set ws = CreateObject("Wscript.Shell")
    rem 调用Wscript.Shell对象的run方法,执行命令。vbhide是run方法的第二个参数,指定了窗口的显示方式:隐藏。
    ws.run "wsl -d CentOS7 -u root /etc/init.wsl", vbhide
    
    1
    2
    3
    4
    5
    6

    命令wsl -d CentOS7 -u root /etc/init.wsl解释:WSL中启动 CentOS 7 发行版,并以 root 用户身份执行 /etc/ 脚本。

    image-20250214154631197

注意:init.wsl 脚本必须预先在WSL发行版本中配置,且具备执行权限。

至此,根据以上操作,即可实现windows开机自动运行wsl,并隐藏窗口,后台运行,且再次打开wsl窗口,关闭后,wsl也不会退出

此外,要想顺利从外网ssh登录wsl2还需要在windows上设置端口映射。端口映射示例:(待验证)

netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=22 connectaddress=127.0.0.1
1

# 二、无法使用systemctl命令的问题(默认未启用systemd)

WSL2 中在使用 systemctl 命令会报错:

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
1
2

WSL2中虽然有systemctl命令,命令位置在/usr/bin/systemctl,但WSL2并没有通过systemd(system daemon,系统守护进程)启动,WSL2中默认没有启用systemd,因此无法使用systemctl命令。

# 解决方式1:(推荐)通过配置启用systemd

【官方】使用 systemd 通过 WSL 管理 Linux 服务 (opens new window)

# 创建
vi /etc/wsl.conf
1
2

wsl.conf 文件中添加以下行,用于 systemd 的 init:

[boot]
systemd=true
1
2

关闭 Linux 发行版,重启即可

# 关闭
wsl.exe --shutdown
1
2

发行版重启后,systemd 将会运行。 可使用 systemctl list-unit-files --type=service 命令进行确认,将显示与 Linux 发行版关联的任何服务的状态。

# 解决方式2:通过安装Distrod启用systemd

这里选择安装Distrod来启用systemd。

Distrod是一个基于systemd的WSL2元发行版,它允许您在一分钟内安装Ubuntu,Arch Linux,Gentoo和许多其他带有systemd的发行版,或者使当前的发行版以systemd运行。Distrod还提供内置的自动启动功能和端口转发服务。这允许您在 Windows 启动时启动 systemd 托管服务,并使其可从 Windows 外部访问。

选择1:直接利用Distro安装WSL发行版本

确保默认WSL版本为 2

# 查询
wsl --status
# 设置默认为WSL 版本为 2
wsl --set-default-version 2
1
2
3
4

下载并解压缩distrod_wsl_launcher-x86_64.zip (opens new window),然后双击exe文件。然后按照向导安装新的发行版。

注意:若要使发行版在 Windows 启动时启动,在WSL2中运行以下命令。

sudo /opt/distrod/bin/distrod enable --start-on-windows-boot
1

选择2:在当前的发行版中运行systemd

  • 下载并运行最新的安装程序脚本。
curl -L -O "https://raw.githubusercontent.com/nullpo-head/wsl-distrod/main/install.sh"
chmod +x install.sh
sudo ./install.sh install
1
2
3
  • 在发行版中启用发行版,有两种选择:

如果要在 Windows 启动时自动启动发行版,请通过以下命令启用 distrod

/opt/distrod/bin/distrod enable --start-on-windows-boot
1

否则

/opt/distrod/bin/distrod enable
1

如果要在以后启用自动启动,则可以再次运行 /opt/distrod/bin/distrod enable --start-on-windows-boot

  • 重新启动发行版

关闭 WSL 的终端。打开一个新的命令提示符窗口,然后运行以下命令。

wsl --terminate Distrod
1

重新打开新的 WSL2 窗口后,shell 将在 systemd 会话中运行。

# 安装完毕后,进行验证

systemctl status | cat
1

#

# 三、使用主机代理的问题

# 在NAT网络模式下使用主机clash代理

思路:clash开启局域网代理,wsl2中设置代理

# 设置代理
export http_proxy='http://<Windows IP>:<Port>' 
export https_proxy='http://<Windows IP>:<Port>'
1
2
3
# 查看代理
echo $http_proxy
echo $https_proxy
1
2
3

实现:自动化脚本

# 添加自动化脚本文件
vi /etc/profile.d/proxy.sh
1
2
#!/bin/sh
# WSL的IP
wslip=$(hostname -I | awk '{print $1}')
# 主机的IP
hostip=$(ip route show | grep -i default | awk '{ print $3}')
# 代理端口,此处<PORT>替换为想要使用的主机的端口号
port=<PORT>
# 代理地址
PROXY_HTTP="http://${hostip}:${port}"

# 设置代理
set_proxy(){
	# http
    export http_proxy="${PROXY_HTTP}"
    export HTTP_PROXY="${PROXY_HTTP}"
	# https
    export https_proxy="${PROXY_HTTP}"
    export HTTPS_proxy="${PROXY_HTTP}"
}

# 取消设置代理
unset_proxy(){
    unset http_proxy
    unset HTTP_PROXY
    unset https_proxy
    unset HTTPS_PROXY
}

# 查询代理设置
test_setting(){
    echo "WSL ip:" ${wslip}
    echo "Host ip:" ${hostip}
    echo "Proxy port:" ${port}
    echo "Current http proxy:" $http_proxy
    echo "Current https proxy:" $https_proxy
}

# 脚本执行:根据输入的命令执行对应分方法
# 获取参数,第1个输入值
param="$1"
# 根据参数执行命令
if [ -z "$param" ] || [ "$param" == "test" ]; then
    test_setting
elif [ "$param" == "set" ]; then
    set_proxy
    test_setting
elif [ "$param" == "unset" ]; then
    unset_proxy
    test_setting
else
    echo "Unsupported arguments."
    test_setting
fi
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

~/.bashrc配置启用和设置别名 proxy

# 备份
cp ~/.bashrc ~/.bashrc.bak
# 编辑
vi ~/.bashrc
1
2
3
4
# 代理脚本别名
alias proxy="source /etc/profile.d/proxy.sh"
1
2
# 加载
source ~/.bashrc
1
2

脚本别名使用

# 测试
proxy test
# 设置代理
proxy set
# 注销代理
proxy unset
1
2
3
4
5
6
上次更新时间: 4/10/2025, 1:04:34 AM