如何在WSL2上设置工作的X11转发

185

当从WSL1迁移到WSL2时,许多事情都会发生变化;显然,这也适用于X11转发。


我需要采取哪些步骤才能像在WSL1上一样在Windows 10上使用WSL2进行X11转发?


4
程序员常用的工具,需要一定的常识。众所周知,并非所有与 WSL2 相关的问题都适合在此讨论,本应永远不应该重新开放这个问题。我们有其他的网站可以讨论此类问题,例如 Super User 更加适合。甚至可能适合于 Ask Ubuntu(假设涉及发行版)或 Unix & Linux Stack。但是,这不是一个关于“特定编码、算法或语言问题”的问题。 - NotTheDr01ds
这个答案帮了我 - https://dev59.com/5lEG5IYBdhLWcg3wY8My - nycynik
1
我强烈建议非程序员甚至意识到WSL是罕见的。X11转发不是主题,但对于要转发的工具的资格(比如证书工具)是有资格的。说一个真正的程序员会依赖命令行是无稽之谈,但也承认这是一个VirtualBox场景是有效的。有解决方法。 - mckenzm
23个回答

2

2021年Windows 10的答案

如果从resolv.conf获取IP地址无法正常工作,请查看此答案。

在WSL2中使用以下命令查找您的Windows IP地址(是的,在Linux内部有.exe文件):

ipconfig.exe 

使用以下命令来设置显示(将YOUR_IP_ADDRESS替换为您的IP):
export DISPLAY=YOUR_IP_ADDRESS:0

检查您的GUI应用程序是否正常工作。

自动化对于每种情况可能会有所不同,但我会举个例子:

ipconfig.exe | grep 'IPv4 Address' | grep '10\.' | cut -d ":" -f 2 | cut -d " " -f 2 

说明:我找到了所有的IPv4地址(在我的情况下是3个IP)。我知道我的IP只从“10.”开始,所以我使用第二个grep选择了这一行。接下来,我处理整行内容,只获取IP地址。


2
我不想搞乱X服务器和Windows防火墙的公共访问。我的解决方案是使用带有X转发的ssh(也适用于VirtualBox)。此外,WSL会自动将主机监听套接字转发到客户端,因此我不需要关心实际分配给客户端的IP地址。
步骤如下:
1.安装VcXSrv。以默认设置运行它,但将显示编号设置为0(如果没有运行任何X实例,则-1将选择0)。不要在其中启动任何客户端(这样可以使您在同一X服务器实例上启动更多应用程序)。
2.打开WSL并配置ssh服务器。对我来说,只需使用sudo service ssh start就可以了。创建一个Windows快捷方式,命令行为:wsl sudo service ssh start。
3.安装Git for Windows。我实际上只使用它,因为它的ssh版本能够使用ssh -f进入后台。Windows版本的ssh在这个功能上存在错误,否则它适合不进入后台或使用ssh -n。
4.从Git-Bash配置无密码登录到guest。此时ssh user@127.0.0.1应该可以工作,因为主机端口被转发到guest。
5.验证X转发是否从Git-Bash起作用:DISPLAY=127.0.0.1:0 ssh -Y user@127.0.0.1 xeyes。我认为每个X发行版都安装了xeyes。
6.在WSL中安装您选择的文件管理器或终端。例如,pcmanfm。创建一个Windows快捷方式:"C:\Program Files\Git\git-bash.exe" -c "DISPLAY=127.0.0.1:0 ssh -Y -f user@127.0.0.1 'bash -l -c pcmanfm >/dev/null 2>&1'"。这里bash -l标志有助于设置可能重要也可能不重要的环境,具体取决于您运行的应用程序。
当然,我也可以使用VcXSrv内置的ssh客户端完成相同的操作,但这需要将ssh密钥转换为PuTTY格式,并且我已经安装了git-bash。此外,使用内置客户端时,显示重用对我没有起作用。

2

来自https://github.com/microsoft/WSL/issues/4793#issuecomment-588321333的解决方案使用VcXsrv作为X服务器,这就是我得到这个答案的地方(稍作编辑以提高可读性)。请注意,原始文档正在由其作者更新,因此不要忘记重新检查。

To make it work:

  1. On Windows, with the following, change E:\VcXsrv to where your installation is, and save it as xxx.bat in your Windows startup folder, e.g., C:\Users\Me\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup, and you can make it run when boot if you like:
@ECHO OFF

REM Start WSL once to create WSL network interface
wsl exit

REM Find IP for WSL network interface
SET WSL_IF_IP=
CALL :GetIp "vEthernet (WSL)" WSL_IF_IP
ECHO WSL_IF_IP=%WSL_IF_IP%
setx "WSL_IF_IP" "%WSL_IF_IP%"
setx "WSLENV" "WSL_IF_IP/u"

REM Change E:\VcXsrv to your VcXsrv installation folder
START /D "E:\VcXsrv" /B vcxsrv.exe -multiwindow -clipboard -nowgl -ac -displayfd 720
GOTO :EOF



:GetIp ( aInterface , aIp )
(
    SETLOCAL EnableExtensions EnableDelayedExpansion
    FOR /f "tokens=3 delims=: " %%i IN ('netsh interface ip show address "%~1" ^| findstr IP') DO (
        SET RET=%%i
    )
)
(
    ENDLOCAL
    SET "%~2=%RET%"
    EXIT /B
)
  1. In WSL, edit ~/.bashrc file to add following lines:
export DISPLAY=$WSL_IF_IP:0
unset LIBGL_ALWAYS_INDIRECT

That's all to make WSL2 work automatically. The idea is to get the private LAN IP of WSL interface on Windows, and use Environment variable to pass it to WSL. WSL then updates this LAN IP to DISPLAY for X-Server connection.

剪贴板也可以很好地使用这个设置。我用Ubuntu 20.04 LTS的WSL2安装进行了测试。


请不要完全禁用防火墙以供wsl接口使用。 - whme
1
@whme 我已经移除了那部分,我想。 - Fuhrmanator
非常感谢,我尝试了几种其他方法,但是出现了一些问题,这个方法很好用! - Antoine Bon

2
我使用以下bash来设置显示屏:
export DISPLAY=$(powershell.exe -c ipconfig | grep -A4 WSL | tail -1 | awk '{ print $NF }' | tr -d '\r'):0

在WSL2中,这会给X服务器提供错误的IP地址。在WSL1中运行正常,但在我的WSL2配置中不行。使用WSL2时,您不希望将X11转发到正在运行的WSL实例的IP地址。它在Windows主机上运行,因此需要主机IP地址而不是WSL地址。这适用于WSL 2中的任何IP地址:export DISPLAY = $(host hostname | grep -oP'(\s)\d+(.\d+){3}' | tail -1 | awk' {print $ NF} '| tr-d'\ r') - D. Charles Pyle

1

我更倾向于在虚拟机中设置一个ssh服务器, 在主机上安装像Xming这样的X11服务器, 然后通过带有X11转发功能的putty连接到本地主机。 不需要调整防火墙规则,也不需要主机IP。


1
我不确定为什么以上答案都对我无效。我使用的是搭载AMD和Nvidia图形卡的ROG Zephyrus,我确定这会导致问题。
whme描述的防火墙设置很重要,但是Linux环境变量对我没有用。在配置文件中有几个标记为nameserver的条目,但没有一个允许连接。
最终,我将它们设置为:
export DISPLAY=$HOSTNAME:0.0
export LIBGL_ALWAYS_INDIRECT=

我正在使用VcXsrv作为X服务器。我还需要将参数设置为-nowgl

很遗憾,这对我来说无法启动git citools。 - user3832429
$HOSTNAME最终在WSL2中解析为127.0.0.1,并且由于网络被虚拟化,它不是Windows主机的本地主机,而是X11服务器未列出的wsl2实例的本地主机。 - ThoSil
这个页面上的东西对我都没用 :( 真是疯狂的事情,Win 10 WSL2,没有什么特别的。 - Dfr

0

我也曾经在WSL中打开X11 GUI时遇到过困难。

我有一个问题,无法检测到正确的IP地址,有时X11服务器会出现奇怪的偏移量,有时会出现0-17的随机数。

我编写了以下脚本来自动化解决此问题,但它有一些依赖项:

  • 这已在CentOS7镜像下进行测试和运行
  • 在您的Linux发行版上安装X11-apps以拥有`xset
  • 安装“timeout”应用程序
  • 通过source ./find_display_ip.sh执行脚本。注意source!您将希望在运行的shell上具有DISPLAY环境变量。
  • 仅通过“Windows终端”或某些将Windows“PATH”合并到WSL shell中的东西运行脚本。例如,对于我来说,在Windows提示符“cmd”中默认情况下不使用此功能。
  • 显然,请确保您的X11服务器具有完全访问权限(“xhost +”或“X11远程访问”是完整的)

没有更多的话,这是脚本源代码:

#!/bin/bash

start_index=$1
start=${start_index:-0}
# check current settings
declare -i stop=0
if [ ! -z "$DISPLAY" ]; then
    timeout 1s xset -display $DISPLAY q &> /dev/null;
    [[ "$?" -eq 0 ]] && echo "Already Set to $DISPLAY" && stop=1;
fi

# scan displays 0-17
for port in $(seq $start 17);
do
    [[ 1 -eq $stop ]] && break;
    grp="ipconfig.exe | grep IPv4 | tr -d '\015' | sed 's#.*: \(.*\)\$#\1:${port}.0#;'"
    for ipd in $(eval $grp)
    do
        echo Trying $ipd;
        timeout 1s xset -display $ipd q &> /dev/null;

        # command was sucessful
        [[ "$?" -eq 0 ]] && export DISPLAY=$ipd && echo $ipd was set && stop=1;

        ##echo "Trying next IP...";
    done
done

0

这里有两篇我写的文章,介绍了如何设置不同类型使用情况下的x11:

  1. 在WSL2中安装带图形用户界面的程序:本文介绍了安装vcxsrv、将环境变量添加到bashrc配置文件中以及编程方式调度vcxsrv在启动时带有命令行参数。还介绍了在WSL2中安装和启动Firefox作为独立程序。
  2. 在WSL2中安装带图形用户界面的Ubuntu桌面:本文介绍了安装vcxsrv、dotNet、genie和Ubuntu桌面。它涵盖了创建导出环境变量的脚本、启动vcxsrv、启动gnome桌面环境以及创建将它们全部绑定在一起的快捷方式。还介绍了运行Ubuntu桌面、防止屏幕锁定错误以及安装Snap Store。

1
已修复,感谢 @HectorJ。 - david-littlefield

0

我发现Ubuntu有一份官方文件非常全面,供您参考。我们知道,这个提示在Debian/WSL2上同样适用。 https://wiki.ubuntu.com/WSL

感谢Kennyhyun和其他人的分享。他们所有的方法都或多或少地在我的电脑上启用了WSL2上托管的X11服务器。由于WSL2作为一个虚拟机已经不再是与WSL1相同的基础架构了。我花了一些时间去了解它。

让我简要地介绍一下如何使WSL2上的应用程序显示出来。

  1. 在 WLS2 终端上运行 'ip route'。

    ip route default via a.b.c.1 dev eth0 a.b.c.0/20 dev eth0 proto kernel scope link src x.x.x.x

  2. 将 "dev eth0" 的 IP 地址添加到 "export $DISPLAY=" 中。

    export $DISPLAY=a.b.c.1:0.0

  3. 运行 xming 服务器。 然后您可以运行在 WSL2 Linux 上运行的应用程序。但对于 X11,您可能需要遵循 Ubuntu 文档。


0
我找到了一个对我有用的解决方案,如下: 在WSL2上设置图形。
1.      Start ssh service
1.1.   Open WSL
1.2.   Type: sudo service ssh start
2.      Get Windows (WSL net) IP
2.1.   Open Powershell
2.2.   Type: (ipconfig | Select-String -Pattern 'WSL' -Context 1, 5).Context.PostContext | Select-String -Pattern 'IPv4'
2.3.   Get the received IP
3.      Set environment variable
3.1.   In WSL2 terminal type: export DISPLAY=172.23.64.1:0.0 with the IP of the windows entity (2.3) instead of the place holder
4.      Launch Xming
4.1.   Open Xlaunch and go with the defaults In Specify parameter settings: Check No Access Control
5.      Good luck!

以下是链接: https://docs.google.com/document/d/1ao3vjbC3lCDc9kvybOT5PbuGhC4_k4g8LCjxX23VX7E


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接