如何检查X服务器是否正在运行?

90

有没有办法找出当前会话用户是否正在运行 X 服务器(在 Linux 下)?

我已经开始尝试以下内容:

ps -e | grep X 

但这并不总是有效。

我尝试的另一件事是检查$DISPLAY变量。

还有其他的检查方法吗?

编辑:

有些人建议使用$DISPLAY变量,但如果用户篡改了此变量怎么办?如果他尝试做某些事情并更改此变量,那么当我检查它时,它就不再反映系统的准确状态了。

是否没有特定的方法可以始终返回正确的答案?

我发现可以通过编程方式实现:

#include <X11/Xlib.h> 
int main()
    { exit(XOpenDisplay(NULL) ? 0 : 1);  } 

$ gcc -o xprobe xprobe.c -L/usr/X11R6/lib -lX11 

但我正在寻找一种脚本方式。


2
为什么“ps -e | grep X”不总是有效? - stephendl
3
为什么 $DISPLAY 没有作用? - Matthew Marshall
@stephendl:我发现在某些情况下,X正在运行,但用户通过没有X的终端连接。 @matthew:如果用户摆弄这个变量,它不再反映系统的实际状态怎么办? - RomanM
6
再挑剔一点,XOpenDisplay函数在内部使用DISPLAY环境变量。 - Anya Shenanigans
@RomanM:我建议您接受得票最多的答案,即使用“xset”的答案。 - jamadagni
显示剩余3条评论
12个回答

85

我经常需要在运行多个X服务器的服务器上运行X命令,因此基于ps的答案无法使用。 自然地,必须适当设置$DISPLAY。 要检查其是否有效,请在类似以下片段中使用xset q

if ! xset q &>/dev/null; then
    echo "No X server at \$DISPLAY [$DISPLAY]" >&2
    exit 1
fi

编辑

有些人发现,在判断$DISPLAY是否指向有效的X服务器时(通常是在使用tcp/ip传输时),xset可能需要让人等待一段烦人的时间。 当然,解决方法是使用timeout来使等待时间可接受,例如1秒。

if ! timeout 1s xset q &>/dev/null; then
    ⋮

我认为这比使用 xpropxdpyinfo 更好,因为 xset 产生的输出较少,可以更轻松地被 /dev/null 处理。楼主应该接受这个答案。 - jamadagni
2
@will 这个挂起问题不仅限于 xset。任何 X 程序都会受到影响。挂起取决于 X 传输机制。比如如果你设置了 DISPLAY=:1,那么这意味着 tcp 端口6001。你可能有一些未知的进程在监听该端口。当没有进程占用时,我的 xset 可以立即返回。 - bobbogo
1
@dstromberg 这不是一个适当的地方来问这个问题!尽管如此:在我的看来,你正在从本地机器_local_通过ssh连接到远程机器_remote_,并且在你的_ssh_中打开了X-forwarding。问题在于原始的_ssh_命令需要访问一个工作的X服务器,并且在_local_上你的$DISPLAY设置得很糟糕。然后发生的事情是你在_remote_上运行一个X命令。_Ssh_将X协议隧道返回到_local_,但由于不良的$DISPLAY而失败,_ssh_打印出消息。 - bobbogo
1
当 X 服务器停止时,这在我的 WSL2 上需要 35 秒才能完成。有没有更快(即刻)的方法来检查 X 服务器是否可用?谢谢。 - Gerard Bosch
1
嗨@bobbogo,我正在尝试使用MobaXterm,并将DISPLAY设置为以下内容(从Windows中获得访问权限):export DISPLAY="$(/sbin/ip route | awk '/default/ { print $3 }'):0"。我需要在shell启动(.profile)时多次运行xmodmap,如果X服务器关闭,则需要很长时间才能回答。我只想在脚本中添加一个守卫来防止这种情况发生。该守卫是关于测试X服务器是否正在运行。 - Gerard Bosch
显示剩余6条评论

22

$DISPLAY是标准方式。这是用户与程序交流关于使用哪个X服务器(如果有的话)的方式。


6
如果我设置了$DISPLAY,那是因为我希望你的程序在不同的显示器中运行。请问你需要什么样的使用情境才要去懒惰地推测用户的明确配置?你是否也避免使用$HOME,以防用户对它进行更改?这种想法何时才会停止呢? - Ken
2
你想要访问哪个X服务器?我经常需要在远程系统上安装驱动程序。此外,在POSIX中,XOpenDisplay(NULL)被定义为简单地读取$DISPLAY,因此最好不要依赖非标准行为。 - Ken
6
如果有一个应用程序在本地主机上运行,但是因为用户是远程登录,所以他们设置了$DISPLAY到另一个服务器,那么你是否仍然想要"本地"的应用程序?如果有多个本地应用程序怎么办?我不知道如何检测它们,也不知道为什么需要检测。$DISPLAY 存在是有原因的。 - Ken
1
您能为那些不熟悉Linux的用户详细解释一下您的答案吗?$DISPLAY是什么?如何使用它? - Paul
3
在Windows(WSL)下,我想测试X是否已经运行。换句话说,我想测试因为我想设置DISPLAY。我可以重新表述为:DISPLAY是由某个假定它知道X正在运行的东西设置的,这与它实际上是否正在运行无关。 - Champignac
显示剩余4条评论

9

我用的一个技巧来判断 X 是否在运行:

telnet 127.0.0.1 6000

如果它连接成功,那么你就有一个正在运行的 X 服务器,并且它接受入站 TCP 连接(这通常不是默认设置)...


1
我猜目前注重安全的系统不会提供“telnet”命令。 - boardrider
3
有安全意识的系统也不会在TCP端口上进行侦听,而是会限制在Unix域套接字上,进一步使这种方法无效化。 - alanc

9
您可以使用xdpyinfo(可以通过apt-get install x11-utils安装)来进行操作。

8

我使用

pidof X && echo "yup X server is running"

pgrep和$DISPLAY是其他选项。

其他注意事项:

su然后$DISPLAY将不会被设置。改变程序运行环境的事情可能会导致它无法工作。

我不建议使用ps -e | grep X,因为这会找到procX,而不是X服务器。


这不就相当于 ps -e | grep X 吗? 据我所知,pidof 只是 killall5 的别名,并不总是在所有系统上定义。 - RomanM
从 man pidof: "pidof 实际上与 killall5 是相同的程序;该程序的行为取决于其被调用时使用的名称。"pidof 的行为与 killall5 不同。如果您使用的是旧版 Unix 系统,则可能不存在该程序。 - Ian Kelling
但是关于大约一百万件事情,同样的话也可以说到旧的Unix系统。 - Ian Kelling

6
xprop -root &> /dev/null 

这是我经过尝试和验证的用于测试“X-able”情况的命令。它几乎可以在任何运行X系统上使用,当然如果命令未找到,则失败,因此即使不存在,您也基本可以认为没有X存在。(这就是我使用&>而不是>的原因)


3
在不支持 &>dash shell 脚本中,可以使用 >/dev/null 2>&1 替代 &> - jamadagni
2
在Cygwin上安装X的典型方法是安装“xinit”软件包。因此,“xprop”不会自动安装,因为它不是依赖项。 - Egor Skriptunoff
1
需要大约500毫秒才能运行,而xset q只需要300毫秒。 - Andy

4
我写了一个名为xdpyprobe的程序,旨在用于此目的。与xset、xdpyinfo和其他通用工具不同,它不执行任何额外操作(只检查X服务器并退出),如果指定了“-q”选项,则可能不会产生任何输出。

4

使用bash脚本的解决方案:

if ! xset q &>/dev/null; then
    echo "No X server at \$DISPLAY [$DISPLAY]" >&2
    exit 1
fi

如果您从另一个控制台(Ctrl+Alt+F?)或ssh登录,则无法正常工作。对我来说,在我的Archlinux中,这个解决方案有效:

#!/bin/sh
ps aux|grep -v grep|grep "/usr/lib/Xorg"
EXITSTATUS=$?
if [ $EXITSTATUS -eq 0 ]; then
  echo "X server running"
  exit 1
fi

您可以将 /usr/lib/Xorg 更改为仅针对 Xorg 或适合您系统的正确命令。


1
在我的情况下,进程名称是/usr/lib/xorg/Xorg而不是/usr/lib/Xorg - ignacio

2

1)

# netstat -lp|grep -i x
tcp        0      0 *:x11                   *:*                     LISTEN      2937/X          
tcp6       0      0 [::]:x11                [::]:*                  LISTEN      2937/X          
仅显示服务器的活动UNIX域套接字
unix  2      [ ACC ]     STREAM     LISTENING     8940     2937/X              @/tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING     8941     2937/X              /tmp/.X11-unix/X0
#

2) nmap

# nmap localhost|grep -i x
6000/tcp open  X11
#

2

首先,您需要确保在服务器上正确安装了基础的X11软件包:

rpm -qa | grep xorg-x11-xauth

如果没有安装,请安装所有的软件包:
sudo yum install xorg-x11-xauth xterm

确保配置了openssh服务器以转发x11连接:

edit file : vim /etc/ssh/sshd_config

X11Forwarding yes

注意:如果这一行前面有注释符 (#) 或设置为 no,则需要更新文件以匹配上述内容,并重新启动您的ssh服务器守护程序(在此要小心 - 如果您犯了错误,可能会将自己锁定在服务器外)。

sudo /etc/init.d/sshd restart

现在,配置SSH应用程序以转发X11请求:
ssh -Y your_username@your_server.your_domain.com

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