Xt错误:无法打开显示器,如果使用默认DISPLAY

21

概述

我正在尝试在OSX上让XQuartz工作,以便通过Docker进行X11转发。我正在遵循这里的说明。我相信我的问题可能仅需要第一部分的答案,但为了避免XY问题,我也提供了第二部分。

安装

我已经通过homebrew安装了它,通过brew cask install xquartz。然后我使用open -a XQuartz来启动它。

本地xterms

测试一下,如果我尝试打开一个xterm,它不起作用:

MacBook-Pro:opencv-gui csaftoiu$ xterm
xterm: Xt error: Can't open display: /private/tmp/com.apple.launchd.3wncZULdXC/org.macosforge.xquartz:0

虚拟文件是存在的:

MacBook-Pro:opencv-gui csaftoiu$ echo $DISPLAY
/private/tmp/com.apple.launchd.3wncZULdXC/org.macosforge.xquartz:0
MacBook-Pro:opencv-gui csaftoiu$ ls -alh $DISPLAY
srw-rw-rw-  1 csaftoiu  wheel     0B May  6 21:12 /private/tmp/com.apple.launchd.3wncZULdXC/org.macosforge.xquartz:0

我可以通过XQuartz打开一个xterm。然后:

bash-3.2$ echo $DISPLAY
:0

这个值在普通的OSX上也适用:

$ DISPLAY=:0 xterm
# opens xterm, waits for it to finish
$

以下内容并不起作用,根据这里的答案,原因不确定:
xterm: Xt error: Can't open display: localhost:0
MacBook-Pro:opencv-gui csaftoiu$ DISPLAY=127.0.0.1:0 xterm
xterm: Xt error: Can't open display: 127.0.0.1:0
MacBook-Pro:opencv-gui csaftoiu$ DISPLAY=`ipconfig getifaddr en0`:0 xterm
xterm: Xt error: Can't open display: 192.168.1.15:0

请注意,xinit 由于某种原因确实可以使用:
$ xinit

xinit: XFree86_VT property unexpectedly has 0 items instead of 1
# opens xterm, waits for it to finish
xinit: connection to X server lost

waiting for X server to shut down

问题1:XQuartz实际上在监听什么?


使用socat进行Docker转发

无论如何,继续前进,这个socat命令不起作用:

MacBook-Pro:opencv-gui csaftoiu$ socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"

在另一个窗口中运行该命令:

MacBook-Pro:opencv-gui csaftoiu$ docker run --rm -it -e DISPLAY=`ipconfig getifaddr en0`:0 ubuntu:14.04 bash
root@912eec31b8cb:/# apt-get update && apt-get install xterm
... such install, wow ...
root@912eec31b8cb:/# xterm
Warning: This program is an suid-root program or is being run by the root user.
The full text of the error or warning message cannot be safely formatted
in this environment. You may get a more descriptive message by running the
program as a non-root user or by removing the suid bit on the executable.
xterm: Xt error: Can't open display: %s
root@912eec31b8cb:/# echo $DISPLAY
192.168.1.15:0

socat 窗口中,我得到:

2016/06/14 21:08:15 socat[24289] E connect(5, LEN=68 AF=1 "/private/tmp/com.apple.launchd.3wncZULdXC/org.macosforge.xquartz:0", 68): Connection refused

我也无法使用有效的DISPLAY变量:

MacBook-Pro:opencv-gui csaftoiu$ socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\":0\"
2016/06/14 21:09:43 socat[24309] E connect(5, LEN=4 AF=1 ":0", 4): No such file or directory

现在,这不是一个UNIX-CLIENT IP。但是,我不知道DISPLAY=:0连接到了什么。它肯定不是端口6000,因为那是它以前侦听的端口。如果我将其更改为6005,以转发到6000,并使Docker容器显示为$(ipconfig getifaddr en0):5,那么连接当然会被拒绝。
$ socat TCP-LISTEN:6005,reuseaddr,fork TCP:localhost:6000
2016/06/14 21:20:32 socat[25379] E connect(8, LEN=16 AF=2 127.0.0.1:6000, 16): Connection refused

问题2:如何从这里开始?

6个回答

24

使用Docker for Desktop MacOS 2018+将UI应用程序容器化。2021年更新。

经历了所有的痛苦,以获得最简单的版本,不依赖于检查端口、IP等...这就是它。

  • 运行版本 XQuartz 2.7.11 (xorg-server 1.18.4)
  • Docker版本 docker version 18.06.1-ce

请确保安装XQuartz(已更新为2021更改)。

$ brew install socat
$ brew install --cask xquartz
  • 不要忘记退出并重新登录。

注意:此时,请务必重新启动您的主机(例如,MacOS)。以下错误与您未这样做有关:E connect(5, LEN=2 AF=1 "<anon>", 2): Invalid argument

$ socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"
2021/04/04 17:28:58 socat[40606] E connect(5, LEN=2 AF=1 "<anon>", 2): Invalid argument

操作说明

  • 您需要打开至少两个终端:一个用于socat显示,另一个用于运行UI容器。

1. 关闭任何6000端口的进程

在一个新的终端中,验证是否有任何进程正在使用6000端口。

$ lsof -i TCP:6000
$

如果有任何问题,只需终止该进程

2. 关闭所有6000端口

在该端口上打开一个socket并保持终端开启

$ socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\"

3. 验证6000端口是否开启

在新的终端中,验证该端口是否已经打开。

$ lsof -i TCP:6000
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
socat   29298 marcellodesales    5u  IPv4 0xe21e43ca9d99bf1d      0t0  TCP *:6000 (LISTEN)

4. 构建和运行简单的UI应用程序

$ cat Dockerfile.eyes

FROM debian:latest
RUN apt-get update && apt-get install -y x11-apps
RUN rm -rf /tmp/* /usr/share/doc/* /usr/share/info/* /var/tmp/*
RUN useradd -ms /bin/bash user
ENV DISPLAY :0
USER user
ENTRYPOINT ["/bin/sh", "-c", "$0 \"$@\"", "xeyes"]

$ docker build -t eyes -f Dockerfile.eyes .

魔法是通过使用Docker的变量实现的。只需使用-e DISPLAY=docker.for.mac.host.internal:0即可完成操作,因为它将指向内部IP地址并将其提供给Docker镜像。端口转发会自动完成其工作。
$ docker run -ti --rm -e DISPLAY=docker.for.mac.host.internal:0 eyes

在此输入图片描述

我注意到此时XQuartz会自动打开到相同的端口。

(注:XQuartz是Mac OS X下的X Window系统,用于运行X Window应用程序)

$ lsof -i TCP:6000
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
socat   29298 marcellodesales    5u  IPv4 0xe21e43ca9d99bf1d      0t0  TCP *:6000 (LISTEN)
X11.bin 29462 marcellodesales    8u  IPv6 0xe21e43ca7cdb1135      0t0  TCP *:6000 (LISTEN)

5. 获利并运行更多应用程序

$ docker run -e DISPLAY=docker.for.mac.host.internal:0 jess/tor-browser

enter image description here

$ docker run -e DISPLAY=docker.for.mac.host.internal:0 batmat/docker-eclipse

enter image description here


这看起来很有前途,但结果的GUI会话不稳定(在30秒内关闭,没有错误消息)。我读到可以在某个地方使用“-t”标志来禁用默认超时,但是关于socat的文档很少,并且在socat TCP-LISTEN'命令中添加“t ignoreof”肯定不起作用(实际上,socat在图形应用程序关闭后仍然继续监听端口6000)。我还遇到了libGL错误:找不到匹配的fbConfigs或visuals libGL错误:无法加载驱动程序:swrast - Kristof

23

我重新安装XQuartz后没有重新启动电脑。现在我重启了电脑,它正常工作了。:)


1
我遵循的指示确实说要注销并重新登录才能使xQuarts工作,我已经这样做了。重启也是我缺失的关键步骤,谢谢! - Jared Chmielecki

2
我需要退出终端并重新启动才能使其正常工作。

终端需要查看使用X安装的新路径。您可以在命令行中添加它,但重新启动终端可以轻松解决这个问题。 - Jeff Clayton

2

这个答案可能仅适用于MacOS/Monterey。

在运行XQuartz并设置首选项/安全性/"允许来自网络客户端的连接"选项后,您必须重新启动XQuartz。(可能情况是,在安装后,您必须再次注销/登录,但我发现仅重新启动XQuartz就足够了。)之后,当XQuartz再次运行时,您应该看到它正在侦听6000端口:

lsof -i TCP:6000

在进行重新启动之前,只有DISPLAY=:0或默认的基于文件的套接字对我有效。经过这一步骤后,我就可以执行以下操作:

export DISPLAY=localhost:0

xtermxhost 等都可以正常工作。

为了与 Docker 一起使用,我使用了:

xhost +localhost
DISPLAY=docker.for.mac.host.internal:0 
docker run -e DISPLAY=$DISPLAY -v /tmp/X11-unix:/tmp/.X11-unix

救命稻草!这在Ventura上对我起作用。奇怪的是,以前通过ssh连接然后运行VirtualBox之类的命令后,XQuartz会自动打开。换句话说,我不需要手动启动XQuartz和重置DISPLAY变量。你在之前的macOS版本上有同样的经历吗? - undefined
关于上述所有内容,我遇到的问题是由于在某个时候禁用了XQuartz在我的登录项中。重新激活它解决了“DISPLAY”问题,并使得当通过启用了“X11”转发的“ssh”连接时请求窗口服务器时,XQuartz再次自动启动。 - undefined

2

对于OS X 10.6.3及更高版本,根据XQuartz 2.7.11说明

如果这是您第一次安装XQuartz,则可能希望注销并重新登录。这将更新您的DISPLAY环境变量,指向XQuartz.app而不是X11.app。如果您仍想继续使用X11.app作为默认服务器(仍然可以手动启动XQuartz.app),则需要使用launchctl(1)禁用/Library/LaunchAgents/org.macosforge.xquartz.startx.plist。

在我的macOS High Sierra上安装XQuartz 2.7.11后,注销并重新登录我的Mac就足以通过我的MacOS终端实现此功能。但是,您也可以通过打开XQuartz终端应用程序(XQuartz > 应用程序 > 终端)来避免注销并重新登录,并从那里运行您的X应用程序。例如:

enter image description here

然后

bash-3.2$ xclock &

如果这是您第一次安装 XQuartz,您可能希望注销并重新登录。谢谢! - Tom Chen

-2

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

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