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

Windows 10 如何在WSL2上设置工作X11转发,windows-10,x11,windows-subsystem-for-linux,x11-forwarding,wsl-2,Windows 10,X11,Windows Subsystem For Linux,X11 Forwarding,Wsl 2,当从WSL1移动到WSL2时,许多事情会发生变化;显然,这也适用于X11转发。 要在Windows 10上使用WSL2的X11转发,就像使用WSL1一样,我需要采取哪些步骤?TL;博士: 将以下内容添加到您的~/.bashrc: export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0 export LIBGL_ALWAYS_INDIRECT=0 export DISPLAY

当从WSL1移动到WSL2时,许多事情会发生变化;显然,这也适用于X11转发。
要在Windows 10上使用WSL2的X11转发,就像使用WSL1一样,我需要采取哪些步骤?

TL;博士: 将以下内容添加到您的
~/.bashrc

export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=0
export DISPLAY=$(awk'/nameserver/{print$2;exit}'/etc/resolv.conf 2>/dev/null):0
导出LIBGL\u始终\u间接=1
在X11 Windows服务器上启用公共访问*

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


如前所述,正如您在中所读到的,WSL2体系结构使用虚拟化网络组件。这意味着WSL2的IP地址与主机不同。 这解释了为什么WSL1的X11转发设置不能简单地传输到WSL2

在关于WSL的UbuntuWiki页面上,您已经可以在下找到适合WSL2的配置。上述Reddit用户也建议使用类似的配置,他还提供了解决方案的另一部分:在Windows下的X11服务器上启用公共访问

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

export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=0
export DISPLAY=$(awk'/nameserver/{print$2;exit}'/etc/resolv.conf 2>/dev/null):0
导出LIBGL\u始终\u间接=1
并在X11 Windows服务器上启用公共访问*

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

*:如果使用,则可以通过禁用额外设置上的访问控制来启用X服务器的公共访问:


或者直接使用
ac
标志调用
vcxsrv.exe
vcxsrv.exe-ac
,正如github问题上所指出的那样。

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

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

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

对于那些可能使用模拟引擎的人,例如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服务器的公共访问和私有访问禁用X11服务器支持的任何访问控制

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


具有较少困难的替代性好X11服务器是和。有关此配置的一些详细信息,请参阅和。

使用
/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

对于一些像我这样只允许私人网络的人来说

尽管他们应该都打勾

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

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

因此,所有4项都应勾选为绿色

那么以上来自@NicolasBrauer的回答对我来说是有效的

例如,在您启动和启动时禁用访问控制

export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=1
抄袭了我的答案

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

先决条件
  • 为了在Windows主机中使用socat,您需要一个运行WSL1的分发版。我相信你可以在powershell中这样做,但我没有时间研究这个。也许有人可以在powershell中编写一个stdio->tcp重定向程序,这样我们就不需要2个WSL发行版了
如何转发X-server连接
  • 让您喜爱的X服务器在Windows上运行。默认情况下,它们将侦听端口6000
  • 在WSL2发行版中,在后台运行以下命令(
    ubuntu
    是安装了socat的WSL1发行版的名称):
  • 基本上,这会建立一个从普通的X unix域套接字到主机端口6000的隧道

    如何将任何TCP连接转发回主机 假设Windows上有一个tcp服务在端口5555上运行。在WSL2发行版中,在后台运行以下命令(
    ubuntu
    是安装了socat的WSL1发行版的名称):

    如何将任何TCP连接从主机转发到WSL2 这只是在做同样的事情,但方向相反。您可以在WSL1发行版中运行以下内容:

    socat TCP-LISTEN:5555,fork EXEC:"/mnt/c/Windows/System32/wsl.exe -d ubuntuwsl2 socat - TCP\:localhost\:5555"
    
    演出
    在我的电脑上,它可以处理高达150MB/s的数据,因此它不是最快的,但对于大多数应用程序来说已经足够快了。

    我通过使用Windows主机的LAN适配器IP,成功地使用了现成的VcXsrv防火墙配置(即无需覆盖/禁用任何防火墙规则)。将以下内容添加到我的
    ~/.bash\u别名中

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

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

    以下解决方法适用于我:

    设置NetFirewallProfile-Name$(获取NetConnectionProfile)。NetworkCategory-DisabledInterfaceAlases$(获取NetAdapter |其中对象名称-类似
    export DISPLAY=$(powershell.exe -c ipconfig | grep -A4 WSL | tail -1 | awk '{ print $NF }' | tr -d '\r'):0
    
    export DISPLAY=$HOSTNAME:0.0
    export LIBGL_ALWAYS_INDIRECT=
    
    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!
    
    @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
    )
    
    export DISPLAY=$WSL_IF_IP:0
    unset LIBGL_ALWAYS_INDIRECT
    
    # 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
    
    C:\Windows\System32\wsl.exe -e htop
    C:\Windows\System32\wsl.exe lynx
    
    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}
    
    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
    
    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
    
    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
    
    #!/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