如何在 WSL2 上设置工作 X11 转发 [关闭]

Posted

技术标签:

【中文标题】如何在 WSL2 上设置工作 X11 转发 [关闭]【英文标题】:How to set up working X11 forwarding on WSL2 [closed] 【发布时间】:2020-07-21 10:48:03 【问题描述】:

当从 WSL1 迁移到 WSL2 时,很多事情都会发生变化;显然这也适用于 X11 转发。 我需要执行哪些步骤才能在 Windows 10 上使用 X11 转发和 WSL2,就像我对 WSL1 所做的那样?

【问题讨论】:

Tools commonly used by programmers 必须具备一定的常识。众所周知,并非所有 WSL2 问题都是这里的主题,而且这个问题永远不应该被重新打开。出于这个原因,我们有姐妹网站,超级用户在这方面要好得多。它甚至可能是 Ask Ubuntu(假设涉及发行版)或 Unix & Linux Stack 的主题。但是不,这不是关于“特定编码、算法或语言问题”的问题。 这个答案对我有帮助 - ***.com/questions/66768148/… 【参考方案1】:

TL;DR:

将以下内容添加到您的~/.bashrc

export DISPLAY=$(awk '/nameserver / print $2; exit' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1
在适用于 Windows 的 X11 服务器上

启用公共访问。*

TCP 端口 6000 添加单独的 入站规则 到 windows 防火墙,以允许 WSL 访问 X 服务器,如 wsl-windows-toolbar-launcher 人员所述。


正如by WSL_subreddit_mod on reddit 所指出的那样,正如您可以在Microsoft's documentation on WSL2 中看到的那样,WSL2 架构使用虚拟化网络组件。这意味着 WSL2 具有与主机不同的 IP 地址。 这就解释了为什么不能简单地将 WSL1 的 X11 转发设置转移到 WSL2。

在有关 WSL 的 Ubuntu Wiki 页面上,您已经可以在 Running Graphical Applications 下找到适用于 WSL2 的配置。上面提到的 Reddit 用户也提出了类似的配置,他还贡献了解决方案的另一部分:在 Windows 下的 X11 服务器上启用公共访问。

这意味着将以下内容添加到您的~/.bashrc

export DISPLAY=$(awk '/nameserver / print $2; exit' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1

并在您的 X11 服务器上启用公共访问 Windows。*

在 Windows 10 上为 WSL2 启用 X11 转发的最重要部分仍然缺失:默认情况下,Windows 防火墙会阻止通过为 WSL 配置的网络接口进行的连接。TCP 端口 6000 需要单独的入站规则,以允许 WSL 访问 X 服务器。创建规则后,如wsl-windows-toolbar-launcher 人员所述,IP 地址范围可以在新创建规则的设置中限制为 WSL 子网,在 Scope 下:172.16 .0.0/12.

*:如果您使用VcXSrv,您可以通过在额外设置中禁用访问控制来为您的 X 服务器启用公共访问: 或者通过ac 标志直接调用vcxsrv.exevcxsrv.exe -ac,正如ameeno 在github 问题上指出的那样。

另外,this SO answer 展示了如何通过 .Xauthority 文件共享密钥,从而为您提供完整的访问控制。

【讨论】:

我刚刚测试了您的解决方案。即使选中了“禁用访问控制”标志,我也必须允许通过 Windows Defender 进行公共访问(“允许应用程序通过 Windows Defender 防火墙进行通信”)。但是,我不必添加额外的入站规则。 @stedes 应添加额外的入站规则以避免允许所有公共网络访问,因为这可能会导致安全问题。 我做了一些细微的修改并让它工作。首先,我使用MobaXterm 而不是 VcXSrv,因为从防火墙的角度来看它似乎更可靠。其次,我使用了以下导出的 ENV 变量。关键区别在于我不依赖/etc/resolv.conf。 export DISPLAY=$(ip route | awk '/default via / print $3; exit' 2>/dev/null):0export LIBGL_ALWAYS_INDIRECT=1 我的 /etc/resolv.conf 包含多个名称服务器条目,其中没有一个是我当前的 IP 地址,所以这会中断。似乎有关于这是如何工作的假设。 对于授权,您还可以通过在 WSL 中运行 xauth generate $DISPLAY . 来生成 ~/.Xauthority 文件,同时 VcXsrv 在禁用授权控制 (-ac) 的情况下运行。然后做cp ~/.Xauthority /mnt/c/Users/<your login>/,下次启动VcXsrv,用-auth C:\Users\<your login>\.Xauthority参数代替-ac【参考方案2】:

我不知道这是否特定于我的配置,但这些解决方案不适用于我的计算机。他们返回地址 192.168.0.254,这是我的网关,而不是我的主机。

为了让它工作,我必须在我的 Ubuntu/WSL2 上使用以下内容:

export DISPLAY="`ip -4 address | grep -A1 eth0 | grep inet | cut -d' ' -f6 | cut -d/ -f1`:0"

【讨论】:

【参考方案3】:

对于可能使用模拟引擎ROS/Gazebo、Unity等的用户,需要另外配置。

将这些添加到~/.bashrc

export DISPLAY=$(awk '/nameserver / print $2; exit' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=0

请务必在 Windows 中为您的 X11 服务器启用 both 公共访问权限私人访问权限另外禁用您的 X11 服务器支持的任何访问控制。

如果您使用VcXSrv,请取消选中Native opengl。 VcXSrv 的最终配置如下:

难度较小的替代优质 X11 服务器是 X410 和 MobaXterm。有关此配置的详细信息,请参阅 here 和 here。

【讨论】:

【参考方案4】:

使用/etc/resolv.conf 名称服务器对我不起作用,因为我在/etc/wsl.conf 中禁用了resolv.conf 生成(我有一个自定义resolv.conf)。

最终您需要 WSL2 主机 IP 地址,这也应该是您的默认路由。这是我的 Debian WSL2 发行版的 ~/.bashrc 条目:

export DISPLAY=$(ip route | awk '/^default/print $3; exit'):0

【讨论】:

ip 路由 | wc -l 151 这应该如何工作?或者换句话说:我们正在寻找的路线是什么。这些天,一条路线有点罕见.... 我爱你!救命稻草【参考方案5】:

对于像我这样只允许私人网络的人,

虽然他们都应该被勾选

Windows Defender 防火墙上应该有停止标志

双击它并允许私人和公共连接,

所以所有 4 个项目都应该打勾为绿色。

然后@NicolasBrauer 的上述回答对我有用。

就像在你 XLaunch 时禁用访问控制和

export DISPLAY=$(awk '/nameserver / print $2; exit' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1

【讨论】:

谁对a general tips for WSL感兴趣 接受的答案与防火墙更改的链接显示了有关限制对端口 6000 和 IP 范围 172.16.0.0/12 的访问的更多详细信息(这很好),但它并不特定于程序(例如这个答案)。对于 MobaXterm,我的 exe 名称是 xwin_mobax.exe。他们也没有真正解释如何导航到 Windows Defender 防火墙中的正确位置。这些额外的图片帮助完成了这个谜题。 这里是另一个切换 VcXsrv 防火墙设置的地方。在我的案例中没有显示安全警报。 记得在应用更新时更新该规则【参考方案6】:

从this github issue复制我的答案。

这个想法是利用通过 stdio 进行通信的能力。

先决条件

为了在 Windows 主机中使用 socat,您需要一个运行 WSL1 的发行版。我相信你可以在 powershell 中做到这一点,但我没有时间研究这个。也许有人可以在 powershell 中编写一个 stdio->tcp 重定向器,那么我们就不需要 2 个 WSL 发行版了。

如何转发 X-server 连接

    让您最喜欢的 X 服务器在 Windows 上运行。默认情况下,他们会监听 6000 端口。 在 WSL2 发行版中,在后台运行以下命令(ubuntu 是安装了 socat 的 WSL1 发行版的名称):
mkdir -p /tmp/.X11-unix/
socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d Ubuntu socat - TCP\:localhost\:6000"

这基本上建立了一条从普通 X unix 域套接字到主机端口 6000 的隧道。

如何将任何 TCP 连接转发回主机

假设有一个 tcp 服务在 Windows 的 5555 端口上运行。在 WSL2 发行版中,在后台运行以下命令(ubuntu 是安装了 socat 的 WSL1 发行版的名称):

socat TCP-LISTEN:5555,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d ubuntu socat - TCP\:localhost\:5555"

如何将任何 TCP 连接从主机转发到 WSL2

这只是做同样的事情,但方向相反。您可以在 WSL1 发行版中运行以下命令:

socat TCP-LISTEN:5555,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d ubuntuwsl2 socat - TCP\:localhost\:5555"

性能

在我的 PC 上,它可以处理高达 150MB/s 的数据,因此它不是最快的,但对于大多数应用程序来说已经足够快了。

【讨论】:

是的!这就是要走的路。我将它添加到我的 startx 脚本中:#!/bin/bash # start Xming X11 if not running if /mnt/c/Windows/System32/tasklist.exe | grep -q Xming.exe;然后 echo 找到 X 服务器 else echo 没有找到 Xserver - 启动它 /mnt/c/Program\ Files\ (x86)/Xming/XLaunch.exe -run '\Users\user\Desktop\config.xlaunch' & # 也启动X11 管道 mkdir -p /tmp/.X11-unix/ socat UNIX-LISTEN:/tmp/.X11-unix/X0,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d Ubuntu-18.04 socat - TCP\:localhost\:6000" & echo 等待一秒 sleep 1 fi【参考方案7】:

我已经设法通过使用 Windows 主机的 LAN 适配器 IP 来使用开箱即用的 VcXsrv 防火墙配置(即,无需覆盖/禁用任何防火墙规则)。将以下内容添加到我的~/.bash_aliases

export DISPLAY=$(pwsh.exe -c ipconfig | grep -A 3 lan | grep IPv4 | head -1 | awk ' print $NF '):0

lan 是我的连接特定的 DNS 后缀(你的可能不同,在这种情况下你应该在上面的命令行中替换它)。

【讨论】:

.bash_aliases 应该用于...别名,而不是导出变量并且您正在从 wsl2 在 Windows 上启动一个命令以获取 ipconfig 的输出,将其传递给 2 个 grep,一个头和一个awk ...每次打开外壳时。仅我笔记本电脑上的 pwsh.exe 就需要 1.125 秒才能运行! 遗憾的是,这对我不起作用有两个原因。我的系统上没有 pwsh.exe。我假设您的意思是 powershell.exe 或在您的 Windows 系统上有一些别名。使用 powershell.exe 时的输出最终在我的系统上如下所示::02.168.0.5。这当然行不通,因为这只是地址的一部分,并且由于某种原因,字符串顺序被翻转了。【参考方案8】:

以下解决方法对我有用:

Set-NetFirewallProfile -Name $(Get-NetConnectionProfile).NetworkCategory -DisabledInterfaceAliases $(Get-NetAdapter | Where-Object Name -like 'WSL').Name

【讨论】:

您所做的是完全禁用 wsl 网络适配器的防火墙。这是一个安全风险,应该避免。【参考方案9】:

我使用以下 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')【参考方案10】:

我宁愿在guest中设置一个ssh服务器, 在主机上安装 Xming 之类的 X11 服务器 并使用 X11 转发通过 putty 连接到 localhost。 无需摆弄防火墙规则,不需要主机 IP。

【讨论】:

【参考方案11】:

我发现有一个来自 Ubuntu 的官方文档,它很全面,供您参考。正如我们所知,这个技巧也适用于 Debian/WSL2。 https://wiki.ubuntu.com/WSL

感谢 Kennyhyun 和其他人的分享。所有这些都是在我的计算机上以某种方式或某种方式在 Windows10 上托管的 WSL2 上启用 X11 服务器。由于 WSL2 作为 VM 不再是与 WSL1 相同的基础架构。我确实花了一些时间来完成它。

请允许我简单地补充一些关于如何在 WSL2 上显示应用的内容。

    在 WLS2 终端上运行“ip route”。

    ip 路由 默认通过 a.b.c.1 dev eth0 a.b.c.0/20 dev eth0 proto kernel scope link src x.x.x.x

    将此“dev eth0”的IP地址添加到“export $DISPLAY="

    导出 $DISPLAY=a.b.c.1:0.0

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

【讨论】:

【参考方案12】:

我不知道为什么,但以上答案都不适合我。我正在使用 AMD 和 Nvidia 显卡的 ROG Zephyrus 运行,我确信这会导致问题。

whme 描述的防火墙设置很重要,但是 linux 环境变量对我不起作用。我在配置文件中有几个标记为名称服务器的条目,其中没有一个允许连接。

我最终将它们设置为:

export DISPLAY=$HOSTNAME:0.0
export LIBGL_ALWAYS_INDIRECT=

我使用 VcXsrv 作为 X 服务器。我还必须将参数设置为-nowgl

【讨论】:

不幸的是,这对我启动 git citools 不起作用 $HOSTNAME 最终在 WSL2 中解析为 127.0.0.1 并且由于网络是虚拟化的,它不是 Windows 主机的本地主机,而是 X11 服务器未列出的 wsl2 实例的本地主机。 此页面上没有任何东西对我有用 :( 疯狂的东西,赢得 10 wsl2,没有什么特别的【参考方案13】:

我找到了一个适合我的解决方案,如下: 在 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

【讨论】:

【参考方案14】:

https://github.com/microsoft/WSL/issues/4793#issuecomment-588321333 的解决方案使用 VcXsrv 作为 X 服务器,这就是我得到这个答案的地方(为了便于阅读,稍作编辑)。请注意,原作者正在对其进行更新,因此请不要忘记重新检查。

为了让它发挥作用:

    在 Windows 上,使用以下命令,将 E:\VcXsrv 更改为您的安装位置,并将其保存为 xxx.bat 在您的 Windows 启动文件夹中,例如,C:\Users\Me\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup,如果您愿意,可以让它在启动时运行:
@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
)
    在 WSL 中,编辑 ~/.bashrc 文件以添加以下行:
export DISPLAY=$WSL_IF_IP:0
unset LIBGL_ALWAYS_INDIRECT

这就是让 WSL2 自动工作的全部内容。这个想法是在Windows上获取WSL接口的私有LAN IP,并使用环境变量将其传递给WSL。 WSL 然后将此 LAN IP 更新为 DISPLAY 以用于 X-Server 连接。

剪贴板在此设置下也能正常工作。我使用 Ubuntu 20.04 LTS 的 WSL2 安装对此进行了测试。

【讨论】:

请不要完全禁用wsl接口的防火墙。 @whme 我认为我删除了那部分。 非常感谢,尝试了其他一些方法但遇到了一些问题,这工作正常!【参考方案15】:

这是我写的两篇文章,介绍了为不同类型的用例设置 x11:

    Install a Program With a Graphical User Interface in WSL2:本文介绍了安装 vcxsrv、将环境变量添加到 bashrc 配置文件以及以编程方式安排 vcxsrv 在启动时使用命令行参数启动。它还包括在 WSL2 中将 Firefox 作为独立程序安装和启动。 Install Ubuntu Desktop with a Graphical User Interface in WSL2 本文介绍如何安装 vcxsrv、dotNet、genie 和 Ubuntu 桌面。它包括创建导出环境变量的脚本、启动 vcxsrv、启动 gnome 桌面环境以及创建将它们联系在一起的快捷方式。它还包括运行 Ubuntu 桌面、防止屏幕锁定错误以及安装 Snap Store。

【讨论】:

已修复,谢谢@HectorJ【参考方案16】:

如何在 WSL2 中设置 X11 转发

此答案假定您已经在 Windows 主机上运行了有效的 XServer 和 PulseAudio 配置,因为您已经在使用 WSL1。 (您可能还必须将 -ac 参数添加到命令行,以使您选择的 XServer 与 WSL2 一起使用。)

我这样做的方式,为了确保无论我在 Windows 主机上使用静态 IP 地址还是 DHCP,甚至我的主机名或网络位置发生变化,我都能获得 X11 转发,我将以下内容添加到我的 ~/.bashrc 文件:

# Get the IP Address of the Windows 10 Host and use it in Environment.
HOST_IP=$(host `hostname` | grep -oP '(\s)\d+(\.\d+)3' | tail -1 | awk ' print $NF ' | tr -d '\r')
export LIBGL_ALWAYS_INDIRECT=1
export DISPLAY=$HOST_IP:0.0
export NO_AT_BRIDGE=1
export PULSE_SERVER=tcp:$HOST_IP

做完以上之后,无论我的Hostname或Host的IP地址是什么,在WSL2中每次启动一个BASH会话时都会被放到环境中。通过从命令行运行 firefox 来测试它并观看 YouTube 视频。您应该能够听到声音并看到应用程序本身来观看视频。此外,通过从命令行启动其他 GUI 应用程序进行测试。

它的作用:它使用 host 命令从输出中提取与主机名关联的 IPv4 地址,greps 匹配包含 Windows 主机 IPv4 地址的行的地址,去除除 IP 之外的其余信息地址,然后 awks 并将其打印到变量中,并修剪输出。然后,它用于提供必要的 IP 地址作为字符串,以在允许转发 X11 和声音输出的环境变量中使用。

如果其他方法对您不起作用(因为它们对我不起作用),希望它对您有用。

大多数 CLI 应用程序都可以从 BASH 提示符或 Windows 终端运行。如果你想创建一个快捷方式,大多数 CLI 应用程序都可以像以下示例之一那样设置(在这种情况下不需要 X11 转发,除了 Links2 之类的应用程序):

C:\Windows\System32\wsl.exe -e htop
C:\Windows\System32\wsl.exe lynx

如果您想为 Linux GUI 应用程序创建桌面快捷方式,除非您可以在启动程序之前从 ~/.bashrc 文件中获取要使用的环境变量,否则您必须使用以下模板创建快捷方式,并将代替 yourprogram 的程序名称:

C:\Windows\System32\wsl.exe LIBGL_ALWAYS_INDIRECT=Yes IP=$(host `hostname` | grep -oP '(\s)\d+(\.\d+)3' | tail -1 | awk ' print $NF ' | tr -d '\r') DISPLAY=$IP:0.0 PULSE_SERVER=tcp:$IP yourprogram

您不必为许多程序放置完整的命令行。对于基于 PERL 的程序或基于 Python 的程序,有时您必须添加 PERL 和 PYTHON 的路径以及程序的完整路径,才能使用 WSL2 在 Linux 中运行此类 GUI 程序。对于我的一个 perl 程序,我必须这样做:

C:\Windows\System32\wsl.exe IP=$(host `hostname` | grep -oP '(\s)\d+(\.\d+)3' | tail -1 | awk ' print $NF ' | tr -d '\r') ; export LIBGL_ALWAYS_INDIRECT=Yes export DISPLAY=$IP:0.0 ; cd /mnt/c/Users/yourusername/Desktop ; /usr/bin/perl ~/wget-gui.pl

您可能需要进行一些试验才能让某些应用正常运行。例如,您可能需要 dbus-launch 应用程序,并且需要将该命令添加到程序名称之前的快捷方式中。

C:\Windows\System32\wsl.exe LIBGL_ALWAYS_INDIRECT=Yes IP=$(host `hostname` | grep -oP '(\s)\d+(\.\d+)3' | tail -1 | awk ' print $NF ' | tr -d '\r') DISPLAY=$IP:0.0 PULSE_SERVER=tcp:$IP dbus-launch --exit-with-session gedit

在某些情况下,您可能必须使用较短的变量名。有些应用程序根本无法正常运行,但随着时间的推移,这种情况正在改善。此外,不要尝试从 Windows 命令提示符或 PowerShell 运行上述命令。它会抛出关于 'grep' 不被识别为内部或外部命令等的错误。

以下是在我的 Windows 10 系统上运行的几个 Linux GUI 应用的屏幕截图,在 WSL2 上运行 X11 转发。

【讨论】:

终于!这是唯一有帮助的解决方案,尝试了一切。只需复制/粘贴第一个命令块,瞧!谢谢! 不客气!很高兴它对你有用。它会增加一到两秒的处理时间,但对于与 IP 地址无关的工作配置来说,这是一个很小的代价。 我在 wsl2 中将它用于 .bashrc,现在它对我有用。【参考方案17】:

您可以在不禁用服务器访问控制的情况下连接到 X 服务器。您在服务器上使用 xauth 生成 cookie,然后在 Linux 端使用 xauth 将其加载到 Linux 中。您可以从 /etc/resolv.conf 获取服务器 IP。以下在我的 .bashrc 中:

k=$('/mnt/c/Program Files/VcXsrv/xauth.exe' -f 'C:\Users\xxx\Documents\scratch.xauth' -i -n -q 2>/dev/null <<EOF
generate localhost:0 . trusted timeout 604800
list
quit
EOF
)
if [ -n "$k" ]
then
        export DISPLAY=$(sed '/^nameserver/ s/^nameserver\s\s*\([0-9][0-9.]*\)[^0-9.]*$/\1/;p;;d' /etc/resolv.conf):0
        xauth -q add $DISPLAY . $k##* 
        export LIBGL_ALWAYS_INDIRECT=true
fi
unset k

【讨论】:

对于Cygwin/X,我不需要生成cookie,而是使用k=$(/mnt/c/cygwin64/rootfs/bin/sh.exe -c '/bin/xauth -n list'|grep "^$DISPLAY") 来获取现有的cookie。我将export DISPLAY=... 行移到该行上方。我还需要将包含exec /usr/bin/XWin -listen tcp "$@".xserverrc 文件添加到cygwin 主目录(cygwin 中的echo 'exec /usr/bin/XWin -listen tcp "$@"' &gt;&gt; ~/.xserverrc),以启用cygwin x 服务器的tcp 访问。 @TS 你能详细说明你是如何让 Cygwin/X 使用 WSL2 作为新答案的吗?我有 VcXsrv 工作,但我听说 Cygwin/X 可以解决我遇到的一些图形故障。不幸的是,我无法从 WSL2 终端启动任何 GUI 应用程序 感谢您发布如何正确执行此操作。所有其他答案都相当危险,因为允许未经身份验证的连接的 X 服务器将允许not only mischief,但也使得附加键盘记录器变得微不足道——只需执行xinput list 获取键盘 ID,然后执行xinput test &lt;n&gt; 即可查看所有关键事件。【参考方案18】:

我不想搞乱对 X 服务器和 Windows 防火墙的公共访问。我的解决方案是使用带有 X 转发的 ssh(也适用于 VirtualBox)。此外,WSL 会自动从主机转发到访客侦听套接字,因此我不关心实际分配给访客的 IP。

所以步骤如下:

    安装 VcXSrv。使用所有默认值运行它,但将 Display number 设置为 0(如果没有 X 实例正在运行,-1 将选择 0)。不要在其中启动任何客户端(这样做的好处是您可以在同一个 X 服务器实例上启动更多应用程序)。 打开 WSL 并配置 ssh 服务器。对我来说就像sudo service ssh start 一样简单。使用命令行创建 Windows 快捷方式:wsl sudo service ssh start。 为 Windows 安装 Git。我实际上使用它只是因为它的 ssh 版本能够以ssh -f 进入后台。 Windows 版本的 ssh 在此功能上存在缺陷,否则无需进入后台或使用ssh -n 即可。 配置从 Git-Bash 到访客的无密码登录。 ssh user@127.0.0.1 此时应该可以工作,因为主机端口已转发给来宾。 从 Git-Bash 验证 X 转发工作:DISPLAY=127.0.0.1:0 ssh -Y user@127.0.0.1 xeyes。我认为每个 X 发行版都安装了 xeyes。 在 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 &gt;/dev/null 2&gt;&amp;1'"。这里bash -l 标志有助于设置环境,这取决于您运行的应用程序可能重要也可能不重要。

当然,我可以在没有 git-bash 的情况下使用 VcXSrv 内置 ssh 客户端来做同样的事情,但它需要将 ssh 密钥转换为 PuTTY 格式,而且我已经安装了 git-bash。此外,内置的客户端显示重用对我不起作用。

【讨论】:

【参考方案19】:

正如其他人指出的那样,我想出了一个在 Windows 10 上使用 vxcsrv 的解决方案。

XServer Windows - WSL1 和 WSL2:

安装 X-Server Windows

https://sourceforge.net/projects/vcxsrv/

在 WSL Distro 中设置向前显示

配置显示

如果您运行 WSL1
export LIBGL_ALWAYS_INDIRECT=1
export DISPLAY=localhost:0
如果您运行 WSL2
export LIBGL_ALWAYS_INDIRECT=1
export DISPLAY=$(awk '/nameserver / print $2; exit' /etc/resolv.conf 2>/dev/null):0
(如果您禁用了resolv.conf,请使用此定义:https://***.com/a/63092879/11473934)

然后(安装 x11-apps)

sudo apt update
sudo apt install x11-apps

在 Windows 上启动 XLaunch

多个窗口 不启动客户端 禁用本机 opengl 启用禁用访问控制

测试一下

在 wsl 中:输入 xcalc - 计算器应该在 Windows10 中打开

如果一切正常

并且您希望将设置保留在您的 wsl 发行版中。将它们存储在您的~/.bashrc

sudo nano ~/.bashrc

复制两行(从Set Display forward in WSL Distro - Configure Display),两行结束并保存。

将其添加到自动启动

    运行对话框请参阅在 Windows 上启动 XLaunch 保存配置 按 Windows + R 输入:shell:startup 将保存的配置:*.launch(在步骤 2 中生成)复制到此文件夹(步骤 4)

现在 XServer 将随着 windows 启动而启动。

我将它用于 ROS。对我有用。

我的 XServer 无法通过 Internet 访问,因此可以禁用访问控制。

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。 它不起作用。 什么不起作用。您是否选中了 Windows 警报中的框(如此处所述:***.com/a/63174434/11473934) 带有访问控制的“在 Windows 上启动 XLaunch”部分帮助了我【参考方案20】:

我的错误是当我的 xserver 在 Windows 上运行时,我使用了我的 linux wsl2 实例的名称服务器。 所以 DISPLAY 变量必须设置为我的 windows ipv4 地址。 只需在 powershell 或 cmd 中输入 ipconfig 并使用 ipv4 ethernet address

【讨论】:

【参考方案21】:

我在从 WSL 打开 X11 GUI 时也遇到了困难。

我在检测正确的 IP 时遇到问题,有时 X11 服务器会采用奇怪的偏移量,有时会在 0-17 上随机出现。

我编写了以下脚本来自动解决这个问题,但它几乎没有依赖关系:

这是在 CentOS7 镜像下测试和运行的 在您的 linux 发行版上安装 X11-apps 以获得 `xset 安装“超时”应用 由source ./find_display_ip.sh 执行脚本。注意来源!您将希望在运行的 shell 上有 DISPLAY 环境变量。 仅通过“Windows Terminal”或在 WSL shell 中包含 windows“PATH”的东西运行脚本。例如,在 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

【讨论】:

【参考方案22】:

2021 答案

Windows 11Insider 版本的 Windows 10,截至 2021 年 4 月 27 日,包括 WSLg。它正常工作™。

注意:目前,所有支持 WSLg 的 Windows 版本都是 Insider 版本,通常不建议日常使用。但是,“WSLg 将与即将发布的 Windows 一起普遍提供”。

来自https://github.com/microsoft/wslg (original announcement)。

先决条件:

    确保使用 Windows 10 Insider build 21362+ 推荐:为vGPU安装驱动程序:IntelAMDNvidia

“系统信息”应用会告诉您当前的内部版本号。

WSL1 is not compatible with WSLg。新的 WSL2 实例将正常工作™。

现有的 WSL2 系统需要“更新”:

    在管理 PowerShell 中:wsl --update wsl --shutdown 强制重启 WSL

不要忘记删除您对DISPLAY 所做的任何其他修改。

证明它有效:

虽然官方公告称 Windows 10 的某些 Insider 版本支持 WSLg,但它已在 上进行了演示Windows 10,目前似乎没有任何公开的 Insider 版本的 Windows 10 支持 WSLg

【讨论】:

***.com/questions/61860208/…【参考方案23】:

2021 年 Windows 10 答案

如果从 resolv.conf 获取 IP 不起作用,请检查此答案。

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

ipconfig.exe 

使用以下命令设置显示(使用您的 IP 填写 YOUR_IP_ADDRESS):

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。

【讨论】:

以上是关于如何在 WSL2 上设置工作 X11 转发 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 上使用 x11 转发在 docker 内运行 Omnet++。 SSH 不工作

linux下如何将GNOME Desktop桌面的信号通过x11转发到当前设备的桌面上?

如何将 X11 转发到运行在远程 linux 主机上的虚拟机?

使用最后一次 CentOS CLEAN 安装设置 X11 转发的完整教程是啥?

Ubuntu 上的 X11 转发错误,尽管它适用于 Windows

MacOS High Sierra 和 X11 转发