技术文章 ·

如何在 Windows 上使用 WSL 2 中的 GUI

因疫情影响,居家办公的场景越来越多。本文将为大家分享如何连接到另一台 Windows 电脑上的 WSL 2,并获得用户图形界面。

X forwarding 到宿主机

X server

WSLg 推出以前,用户将 WSL 2 中的图形界面 X forwarding 到 Windows 宿主机中,需要将 WSL 中的DISPLAY环境变量改变:

export DISPLAY=$(ip route list default | awk '{print $3}'):0
export LIBGL_ALWAYS_INDIRECT=1

将上面的代码添加到用户文件夹下.bashrc 中,可以在开启会话后自动覆盖 DISPLAY 环境变量。其次,需要确保 WSL 2 中的 sshd 服务允许 X forwarding。在/etc/ssh/sshd_config中添加:

X11Forwarding yes

然后重启 sshd

service sshd restart

Windows 自带的 openssh 已经支持 X forwarding,只需要安装 X server(如 vcXrv、Xming),并在 Windows 系统中添加环境变量DISPLAY=localhost:0。不需要如 putty 等其他第三方软件就可以实现在 Windows 显示 WSL 或远程 Linux 系统上运行软件的图形界面。

请检查 C:\Windows\System32\OpenSSH 下的 ssh.exe 文件版本是否大于 v8.1,否则请更新 Windows 10 或升级到 Windows 11

WSLg

WSLg 让用户无需在 Windows 上安装 X server 即可显示 GUI。如果你想通过 WSLg 来显示 GUI,记得把刚才提到的环境变量删除哦。 详情参见:https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps

X forwarding 到局域网中的其他 Windows 电脑

THE EASY WAY how to SSH into Bash and WSL2 on Windows 10 from an external machine这篇文章提供了一种非常简单的方法可以从其他电脑访问 WSL 2,将 WSL 2 的 bash.exe 作为默认终端打开。然而这种方法并不能 X forwarding。另外,ssh 到宿主机 Windows 再 ssh 到 WSL 2 也无法 X forwarding 到远程机器上。

想要使用 GUI, 需要从其他电脑通过 proxy ssh 到 WSL 2 或者直接 ssh 连接到 WSL 2。

直连

WSL 2 最新版实装了mirrored networking mode网络模式,不再需要下面提到的WSLHOSTPATCHER了。

WSLHOSTPATCHER可以将 WSL 2 暴露在 LAN 中,其 IP 地址与 Windows 宿主机相同(端口号需要自定义,通常我喜欢用 2222)。这样就可以直接连接了。

二段跳

参考: https://serverfault.com/questions/53080/how-to-enable-ssh-x11-forwarding-through-additional-server

所谓二段跳就是转发 ssh 端口:首先,连接到机器 B 并通过 B 转发 [localPort] 到 C:22

A$ ssh -L [localPort]:C:22 B &

接下来,使用 [localPort] 通过这个新创建的隧道从 A 连接到 C,转发 X11

A$ ssh -X -p [localPort] localhost

现在我们可以在 C 上运行 X11 程序并在 A 上显示它们啦,试着显示个时钟吧:

C$ xclock

[localPort] 可以是你尚未在 A 上收听的任何端口,为简单起见,我经常使用 2022。 例如:

ssh -NL 2022:localhost:222 nustar-jy &
ssh -Y -p 2022 yuejin@localhost

你也仅通过一行命令实现二段跳

参考: https://superuser.com/questions/1622581/ssh-into-wsl-from-another-machine-on-the-network#1622603

ssh -Y -o "ProxyCommand ssh -W %h:%p nustar-jy" -o "StrictHostKeyChecking=no" -p 2222 yuejin@localhost

或者把相关参数写入.ssh/config文件中,这样你只需要连接proxy-wsl这个 host 就 ok 了。

Host proxy-wsl
    HostName localhost
    User yuejin
    ProxyCommand ssh -W %h:%p nustar-jy
    StrictHostKeyChecking no
    Port 222

注意如果你是通过 ssh 的方式连接到 WSL 2,而不是直接打开wsl.exe,你不需要在 WSL 2 中设置任何环境变量。DISPLAYXAUTHORITY会自动设置成正确的值。如果DISPLAY没有被设置,这说明 ssh 没有在 forwarding X11 链接。