我在 Windows 10 上安装了 WSL Ubuntu 20.04。我还安装了 VcXsrv(Xlaunch)。我使用以下命令启动 VcXsrv:
"C:\Program Files\VcXsrv\vcxsrv.exe" :0 -ac -terminate -lesspointer -multiwindow -clipboard -wgl -dpi auto
在 Ubuntu 终端上,我无法启动终结器。请帮忙。
$ export DISPLAY=0:0
$ terminator
Unable to init server: Could not connect: Connection refused
Unable to init server: Could not connect: Connection refused
You need to run terminator in an X environment. Make sure $DISPLAY is properly set.
以下是 netstat 的输出
C:\Windows\system32>netstat -abno|findstr 6000
TCP 0.0.0.0:6000 0.0.0.0:0 LISTENING 42548
TCP 127.0.0.1:6000 127.0.0.1:65381 ESTABLISHED 42548
TCP 127.0.0.1:6000 127.0.0.1:65382 ESTABLISHED 42548
TCP 127.0.0.1:6000 127.0.0.1:65383 ESTABLISHED 42548
TCP 127.0.0.1:65381 127.0.0.1:6000 ESTABLISHED 42548
TCP 127.0.0.1:65382 127.0.0.1:6000 ESTABLISHED 42548
TCP 127.0.0.1:65383 127.0.0.1:6000 ESTABLISHED 42548
TCP [::]:6000 [::]:0 LISTENING 42548
Get-NetFirewallApplicationFilter |? { $_.Program -like "*vcxsrv*" } | Get-NetFirewallRule
Name : TCP Query User{81BBD37C-DC9F-4C50-B2C6-A1B58CABD66C}C:\program files\vcxsrv\vcxsrv.exe
DisplayName : VcXsrv windows xserver
Description : VcXsrv windows xserver
DisplayGroup :
Group :
Enabled : True
Profile : Domain
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : DeferToUser
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : The rule was parsed successfully from the store. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
RemoteDynamicKeywordAddresses :
Name : {14B2C126-9C6A-42CA-B496-62F2D88ED067}
DisplayName : VcXsrv windows xserver
Description : VcXsrv windows xserver
DisplayGroup :
Group :
Enabled : True
Profile : Public
Platform : {}
Direction : Inbound
Action : Block
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : The rule was parsed successfully from the store. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
RemoteDynamicKeywordAddresses :
Name : UDP Query User{87720067-4851-485C-A9B1-ABE74E6BE131}C:\program files\vcxsrv\vcxsrv.exe
DisplayName : VcXsrv windows xserver
Description : VcXsrv windows xserver
DisplayGroup :
Group :
Enabled : True
Profile : Domain
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : DeferToUser
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : The rule was parsed successfully from the store. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
RemoteDynamicKeywordAddresses :
Name : {1B4ABAF3-28C3-42F8-8C62-3AE54EFFC97C}
DisplayName : VcXsrv windows xserver
Description : VcXsrv windows xserver
DisplayGroup :
Group :
Enabled : True
Profile : Public
Platform : {}
Direction : Inbound
Action : Block
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : The rule was parsed successfully from the store. (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
RemoteDynamicKeywordAddresses :
答案1
我最初投票关闭此帖子,因为它重复了一般如何使用适用于 Linux 的 Windows 子系统运行 GUI 应用程序但实际情况有些不同。
我们确实没有通用的,“我如何确定DISPLAY
WSL 的正确变量?”问题由于我们最终在评论中对此进行了故障排除,因此让我在答案中介绍一下这里的各种选项。
首先,一些“搜索词”。在 WSL 中尝试运行 Linux GUI 应用程序时,您可能会遇到不同的错误:
Error: Unable to open display
Error E233: cannot open display
Error: (SDL_Init) No available video device
(来自 SDL 应用程序)Error: An OpenGL context could not be created
首先,请阅读如何使用适用于 Linux 的 Windows 子系统运行 GUI 应用程序。您需要选择其中一种解决方案才能在 WSL 中运行 Linux GUI 应用程序。
但如果您仍然遇到问题,那么您可能需要采取额外措施。
WSL2:带有 WSLg 的 Windows 11
如果您将 Windows 11 与 WSLg(在 Windows 11 中运行 Linux GUI 应用程序的默认 WSL 选项)一起使用,则DISPLAY
WSL 应该为您设置变量。它应该是:
$ echo $DISPLAY
:0
这相当于DISPLAY=localhost:0
,因为 WSLg 在 WSL2 VM 内部运行,所以它对于您的 WSL 会话来说是“本地的”。
防火墙规则也应自动为您设置。
你应该:
$ echo $WAYLAND_DISPLAY
wayland-0
用于运行 Wayland 应用程序(X 的后继者)。
如果这些变量未正确设置:
检查您的启动配置文件,看看您(或您安装的应用程序)是否将其设置
DISPLAY
为其他内容。尝试启动 WSL(从 PowerShell),而不运行 Bash 启动:
wsl ~ -e bash --noprofile --norc
然后再次检查变量。如果它们现在正确,那么某物启动时更改了它们。您需要编辑启动配置,找到罪魁祸首并修复它。
您是否正在运行 Systemd 启用脚本?如果是,请尝试不使用它。默认情况下,Systemd 环境没有
DISPLAY
(和其他内置 WSL 变量)。大多数 Systemd 启用脚本都会尝试处理这个问题,但它可能会遇到意想不到的极端情况。
WSL1:带有第三方 X 服务器的 Windows 10 或 11
当在 WSL1 中使用第三方 X 服务器(如 VcXsrv)(如此处的原始问题所示)时,应该DISPLAY
再次为:0
,与上面的 WSLg 一样。
$ echo $DISPLAY
:0
WSL1 运行在同一网络中作为 Windows 主机,因此 VcXsrv(等)将是当地的到 WSL1。
使用第三方 Windows X 服务器运行 WSL1 时不需要特殊的防火墙规则。
WSL2:带有第三方 X 服务器的 Windows 10 或 11
这是最复杂的情况,也是原始问题所涵盖的情况。您至少需要两件事才能在 WSL2 下与 VcXsrv(等)进行通信:
- 变量的正确 IP 地址
DISPLAY
。 - 允许访问的防火墙规则
这两者都是必需的,因为 WSL2 在独立网络比 Windows 主机更安全。它使用虚拟交换机后面的虚拟网络接口运行,该虚拟交换机已进行 NAT。因此,localhost:0
(或简称:0
)指的是WSL2网络接口,不是Windows 主机。
在默认的 WSL2 配置中,DNS 解析器(由 WSL)设置为 Windows 主机,使用该虚拟交换机的 IP 地址。因此,您可以尝试多种选项来确定正确的 IP DISPLAY
:
export DISPLAY="$(hostname).local:0"
这使用了 mDNS,该功能在过去几年中已在 WSL2 中提供。请参阅Stack Overflow 上的这个答案了解更多信息。这确实要求使用默认解析器。
export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
这将解析
/etc/resolv.conf
以获取解析器正在运行的 Windows 主机的 IP 地址。同样,这需要使用默认的 WSL2 解析器。export DISPLAY=$(host
主机名--long| grep -oP '(\s)\d+(\.\d+){3}' | tail -1 | awk '{ print $NF }' | tr -d '\r')
如果以上两个选项不起作用,那么(信用这个 Ask Ubuntu 答案,则此选项将尝试获取基本的网络接口。通常这是一个私有网络地址,如
192.168.1.100
或10.0.1.5
。如果这个地址是静态的,你可以简单地对其进行硬编码,这对 OP 有效:
export DISPLAY=192.168.1.100:0` # Adjust with your actual IP
如果它是动态分配的并且经常更改,那么您可以使用上述命令尝试获取它。但是,请注意,这是很多比其他任何方法都慢。在我相对较快的系统上,大约需要 3 秒钟才能完成。
防火墙规则
当将 WSL2 与第三方 X 服务器一起使用时,您还需要确保防火墙允许从 WSL2 访问 Windows 主机。
首次尝试连接到 X 服务器时,Windows Defender应该显示一个对话框,您可以在其中允许从公共和/或私有网络进行访问。不幸的是,WSL2 网络在 Windows 主机中被视为“公共”,因此您需要确保选择了公共。
注意:根据我的经验,对话框经常出现在后面其他窗口,很容易被忽略。如果发生这种情况,并且关闭该对话框而不允许流量,则可能会设置“拒绝”规则。
但是,此处的公共“允许”规则还意味着防火墙将允许其他公共网络(如公共 wifi 网络)上该端口的流量。如果您在不在家中的网络上运行 X 服务器,这可能会带来安全风险。
首先,确保规则到位允许至少可以访问。从管理 PowerShell 会话中:
Get-NetFirewallApplicationFilter |? { $_.Program -like "*vcxsrv*" } | Get-NetFirewallRule
调整-like
你的 X 服务器的可执行文件的选项。
此时,最简单的方法可能是DisplayName
在输出中查找。然后运行Windows Defender 防火墙从开始菜单,找到关联规则入境规则. 确保(至少)公共网络有“允许”规则。
这个答案有点长,添加有关将防火墙规则限制为来自 WSL2(而不是其他公共网络)的流量的信息可能有点超出范围。如果有人对如何做到这一点感兴趣,请就该特定主题发布单独的问题。