90

Is there any way to find out if the current session user is running an Xserver (under Linux) ?

I've started off with things like:

ps -e | grep X 

but this doesn't work always

and one more thing I tried is checking the $DISPLAY variable

Are there any other ways to check this?

EDIT:

Some people suggested using the $DISPLAY variables but what if the user fiddles with this variable ? what if he tries to do something and changes this variable and then when I check it, it no longer reflects an accurate state of the system. Is there no specific way to do this that will always return a correct answer ?

I found that it can be done programmatically thus:

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

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

But I am looking for a script way.

thor
  • 21,418
  • 31
  • 87
  • 173
RomanM
  • 6,363
  • 9
  • 33
  • 41
  • 2
    why doesn't "ps -e | grep X" always work? – stephendl Mar 12 '09 at 01:18
  • 3
    And why doesn't $DISPLAY work? – Matthew Marshall Mar 12 '09 at 01:22
  • @stephendl:I found that in some situations X is running but the user is connected through a terminal with no X @matthew: What if the user fiddles with this variable and it no longer reflects the actual state of the system ? – RomanM Mar 12 '09 at 01:39
  • Just a nit pick: there's no point in calling exit() in your C program to test for X, just return the status and you're done. – unwind Mar 12 '09 at 09:04
  • 6
    And to nitpick a little more... the XOpenDisplay makes use of the DISPLAY environment variable internally. – Anya Shenanigans Mar 12 '09 at 09:07
  • @RomanM: I recommend you accept the answer with the most votes i.e. the one with `xset`. – jamadagni Nov 20 '15 at 03:45
  • @RomanM so you do not want to know, if X is running. You want to know, if the current login is connected to X server. Please change your question to indicate what you are really asking. – jarno Mar 05 '22 at 10:58
  • There are several different questions here, and different answers below answer different questions: 1) is the host running an X server 2) is the 'current session user' (whatever that is; probably refers to the Linux user running a shell, from which the inquiry will be made) running an X session 3) is this very shell session connected to a running X server and able to use it. – reinierpost Aug 24 '22 at 09:27

12 Answers12

84

I often need to run an X command on a server that is running many X servers, so the ps based answers do not work. Naturally, $DISPLAY has to be set appropriately. To check that that is valid, use xset q in some fragment like:

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

EDIT

Some people find that xset can pause for a annoying amount of time before deciding that $DISPLAY is not pointing at a valid X server (often when tcp/ip is the transport). The fix of course is to use timeout to keep the pause amenable, 1 second say.

if ! timeout 1s xset q &>/dev/null; then
    ⋮
bobbogo
  • 14,989
  • 3
  • 48
  • 57
  • I think this is "better" than using `xprop` and `xdpyinfo` since `xset` produces less output for `/dev/null` to eat. The OP should accept this answer. – jamadagni Nov 20 '15 at 03:44
  • When there is no X-Server running at all at the $DISPLAY address, `xset` just hangs, indeed as to all the X-commands. Is there a way to set a time-out? – will Aug 14 '18 at 04:42
  • 2
    @will This hang won't be specific to `xset`. Any X program will suffer it. The hang depends on the X transport. If you have `DISPLAY=:1` say, this implies tcp port 6001. You may have some rouge process listening. My `xset` returns immediately when nothing is listening. – bobbogo Aug 30 '18 at 15:07
  • This is good, but why is it noisy? I keep getting "connect /tmp/.X11-unix/X1: No such file or directory", even if I redirect stdout and stderr to /dev/null. I strace'd it, and it doesn't appear to be getting written by xset. I also strace'd the relevant sshd and it doesn't seem to be writing it either. xset, xdpyinfo and the test program in the original question all output this useless error message. – dstromberg Jun 30 '19 at 04:04
  • 1
    @dstromberg This is a pretty inappropriate place for this question! Nevertheless: it looks to me like you are ssh-ing from a local machine _local_ into a remote machine _remote_, with X-forwarding turned on in your _ssh_. The problem is that the original _ssh_ command needs access to a working X server, and it looks to me that you have a badly set `$DISPLAY` on _local_. What then happens is you run an X command on _remote_. _Ssh_ tunnels the X protocol back to _local_ which fails (due to the dodgy `$DISPLAY`) and _ssh_ prints the message. – bobbogo Jul 01 '19 at 12:31
  • @bobbogo I'm not sure, from my question, why you'd think I didn't know that. My question is: Why can't I redirect the error message somewhere? Not: Why is this an error condition? Please see https://stackoverflow.com/questions/56825547/why-does-x11-output-connect-tmp-x11-unix-x1-no-such-file-or-directory . It's a surprisingly complex issue. – dstromberg Jul 04 '19 at 03:31
  • 1
    This takes 35 seconds in my WSL2 (Windows Subsystem for Linux) to finish when the X server is stopped. Is it any faster (instantaneously) way just to check if the X server is available? Thx. – Gerard Bosch Jul 30 '20 at 07:42
  • @Gerard Which X server are you using, and what protocol are you talking to it with (i.e., what is your `$DISPLAY` set to)? – bobbogo Jul 30 '20 at 08:36
  • 1
    Hi @bobbogo I'm trying with `MobaXterm` and I set DISPLAY to this (which give me access from Windows): `export DISPLAY="$(/sbin/ip route | awk '/default/ { print $3 }'):0"`. I need to run `xmodmap` several times on shell startup (.profile) which takes a lot to answer if X server is down. I just want to add a guard in the script to prevent it. The guard is about test if X-server is running. – Gerard Bosch Jul 30 '20 at 10:55
  • @Gerard A comment stream is not the place to dicuss this. I think you need to raise a question. You have not explcitly answered my question about `$DISPLAY`, but it looks as though you may be connecting to the XServer over tcp/ip. WSL2 does some interesting network translation, and that may be where your problem lies. – bobbogo Jul 30 '20 at 14:02
  • I think [`xhost`](https://unix.stackexchange.com/a/338862) is the better option. Especially if you're concerned with how much `/dev/null` eats. – young_souvlaki Nov 15 '22 at 20:18
22

$DISPLAY is the standard way. That's how users communicate with programs about which X server to use, if any.

Ken
  • 2,651
  • 3
  • 19
  • 17
  • but what if the user fiddles with this variable ? what if he tries to do something and changes this variable and then when I check it, it no longer reflects an accurate state of the system. Is there no concrete way to do this? – RomanM Mar 12 '09 at 01:44
  • 6
    If I set $DISPLAY, it's because I want your program to go to a different display. What exactly is your use case where you want to second-guess the user's explicit configuration? Do you avoid using $HOME in case the user "fiddles" with that, too? Where does it end? – Ken Mar 12 '09 at 01:53
  • i don't want to second guess, just bullet-proof. The use case is for a driver installer, one of the prerequisites is having x running. And I wouldn't avoid using $HOME but ill check it points to an exsisting directory first just in case ^^ – RomanM Mar 12 '09 at 02:06
  • 2
    Which X server, exactly, do you want to access? I've many times had to install drivers on remote systems. Also, in POSIX XOpenDisplay(NULL) is defined to simply read $DISPLAY, so at best it sounds like you're counting on nonstandard behavior. – Ken Mar 12 '09 at 02:20
  • There is not particular X I want to detect, my installer just needs to know that the user is running it with one present. – RomanM Mar 12 '09 at 02:44
  • 6
    I mean, if there's one running on localhost but they set $DISPLAY to another server because they're logged in remotely, do you still want the "local" one? What if there's more than one local one? I don't know how you'd detect that, or why you'd want to. $DISPLAY exists for a reason. – Ken Mar 12 '09 at 04:14
  • 1
    Could you elaborate your answer for users not from the Linux world? What is $DISPLAY? How to use it? – Paul May 21 '19 at 11:39
  • I *think* @Ken means for us to say `echo $DISPLAY` but I'm not 100% sure what the expected output should be. – ComputerScientist Apr 27 '20 at 16:58
  • 2
    Under Windows (WSL), I want to test whether X is already running or not. In other words, I want to test BECAUSE I want to set DISPLAY. I may rephrase DISPLAY is set by something that assumes it knows X is running, it has nothing to do with the fact it is actually running. – Champignac Dec 10 '20 at 12:08
9

You can use xdpyinfo (can be installed via apt-get install x11-utils).

Vito Gentile
  • 13,336
  • 9
  • 61
  • 96
shuckc
  • 2,766
  • 1
  • 22
  • 17
9

I use

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

pgrep and $DISPLAY are other options.

Other considerations:

su then $DISPLAY will not be set. Things that change the environment of the program running can make this not work.

I don't recommand ps -e | grep X as this will find procX, which is not the X server.

Ian Kelling
  • 9,643
  • 9
  • 35
  • 39
  • Isn't this the same as ps -e | grep X ? AFAIK pidof just an alias for killall5 and is not always defined on all systems – RomanM Mar 12 '09 at 01:42
  • From man pidof: "pidof is actually the same program as killall5; the program behaves according to the name under which it is called." pidof behaves differently than killall5. If your using an old old unix system it may not be there. – Ian Kelling Mar 12 '09 at 02:51
  • But the same thing can be said about old unix systems regarding about a million things. – Ian Kelling Mar 12 '09 at 02:55
9

One trick I use to tell if X is running is:

telnet 127.0.0.1 6000

If it connects, you have an X server running and its accepting inbound TCP connections (not usually the default these days)....

dicroce
  • 45,396
  • 28
  • 101
  • 140
  • 1
    I guess at present, security-conscious systems would not have the `telnet` command available. – boardrider Jun 11 '17 at 11:47
  • 2
    Security-conscious systems won't be listening on a TCP port either, but would be restricted to Unix domain sockets, further invalidating this method. – alanc Jan 05 '19 at 18:28
6
xprop -root &> /dev/null 

...is my tried & true command to test for an "X-able" situation. And, it's pretty much guaranteed to be on any system running X, of course, the command fails if not found anyways, so even if it doesnt exist, you can pretty much assume there is no X either. (thats why I use &> instead of >)

osirisgothra
  • 2,163
  • 24
  • 19
4

I wrote xdpyprobe program which is intended for this purpose. Unlike xset, xdpyinfo and other general tools, it does not do any extra actions (just checks X server and exits) and it may not produce any output (if "-q" option is specified).

Alex Kost
  • 41
  • 1
4

The bash script solution:

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

Doesn't work if you login from another console (Ctrl+Alt+F?) or ssh. For me this solution works in my 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

You can change /usr/lib/Xorg for only Xorg or the proper command on your system.

oml
  • 115
  • 2
  • 8
2

First you need to ensure foundational X11 packages are correctly installed on your server:

rpm -qa | grep xorg-x11-xauth

If not then, kindly install all packages :

sudo yum install xorg-x11-xauth xterm

Ensure that openssh server is configured to forward x11 connections :

edit file : vim /etc/ssh/sshd_config

X11Forwarding yes

NOTE : If that line is preceded by a comment (#) or is set to no, update the file to match the above, and restart your ssh server daemon (be careful here — if you made an error you may lock yourself out of the server)

sudo /etc/init.d/sshd restart

Now, configure SSH application to forward X11 requests :

ssh -Y your_username@your_server.your_domain.com
User not found
  • 2,129
  • 2
  • 15
  • 20
Srijan Chaudhary
  • 637
  • 1
  • 8
  • 18
2

1)

# netstat -lp|grep -i x
tcp        0      0 *:x11                   *:*                     LISTEN      2937/X          
tcp6       0      0 [::]:x11                [::]:*                  LISTEN      2937/X          
Active UNIX domain sockets (only servers)
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
#
vitaly.v.ch
  • 2,485
  • 4
  • 26
  • 36
1
if [[ $DISPLAY ]]; then 
  …
fi
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Serge Stroobandt
  • 28,495
  • 9
  • 107
  • 102
0

This is PHP script for checking.

$xsession = `pidof X`;
if (!$xsession) {
    echo "There is no active X session, aborting..\n";
    exit;
}

Similar command can be used in shell script too. like the pidof command.