How to find out the current (active) XServer DISPLAY number?

42,935

Solution 1

You may try to use loginctl list-sessions to get the list of sessions, and then use loginctl show-session -p Display -p Active <session ID> on each of these to get the X11 display number associated with the currently active session.

Something like this (in bash):

TARGET_DISPLAY=()
while read id uid user seat; do
    while IFS='=' read property value; do
        case "$property" in
        Active)
            if [[ "$value" != "yes" ]]; then continue; fi
            ;;
        Display)
            if [[ "$value" ]]; then
                TARGET_DISPLAY+=( "$value" )
            fi
            # else the session isn't graphical
            ;;
        esac
    done < <(loginctl show-session -p Display -p Active "$id")
done < <(loginctl list-sessions --no-legend)

Here the $TARGET_DISPLAY is an array, because hypothetically there may be more than one active session (on a multi-seat system). If this is not possible in your configuration, you may make it a simple variable and add a break 2 statement after the assignment to exit both loops.

HOWEVER...

...this does not anymore work with GDM, because in this case the X server is started inside the session (with user privileges) and /usr/bin/gdm-x-session does not communicate this information back to logind (due to lack of an API for that).

In other cases (when the X server is started by the DM before the session is created) this will most probably work. I'm not aware of any other methods, sorry.

Solution 2

Well, as current I mean active Display of a XOrg Server. Remember that we can have more than one XOrg Server running and they can be multi-head, what make the things harder to manipulate.

The other important note is that the DISPLAY variable in some cases cannot be accessed (eg. systemd).

After some discussion in commandlinefu, I got this result:

for p in $(pgrep -t $(cat /sys/class/tty/tty0/active));
do 
    d=$(awk -v RS='\0' -F= '$1=="DISPLAY" {print $2}' /proc/$p/environ 2>/dev/null); 
    [[ -n $d ]] && break; 
done;
echo $d

This snippet iterates over a list of all processes (actually their IDs) where the controlling terminal is set and matches the terminal of this process. It checks each process' environment for the DISPLAY variable and is satisfied as soon as it finds one. Having found a DISPLAY variable it stops iterating the list and echos the result.

That will print the active display which run the script.

Solution 3

Here's an example with two servers running on the same host. I used startx to launch both of them, as you can see from the output of pstree -pl below. The first child process with $DISPLAY set is .xinitrc:

|-login(698)---zsh(1077)---startx(1359)---xinit(1381)-+-.xinitrc(1386)...

This is the command; if you have a different setup, you could change .xinitrc to something else here:

$ pgrep .xinitrc | while read i; do \
    d=$(cat /proc/$i/environ | tr '\0' '\n' | grep DISPLAY); \
    echo -n $d" "; eval $d xprintidle; \
  done | sort -n -k 2
DISPLAY=:1 93
DISPLAY=:0 603301

The numbers show the idle time of each display, in milliseconds. The top line shows the most recently active (least idle) display.

For what it's worth, none of the other answers worked for me.

Solution 4

This is my solution based on other answers:

#!/bin/bash

DISPLAY=""

# Guess the active DISPLAY
while read session; do
    # Explode to needed variables
    set -- $session; tty=$2; display=$3
    # If there is an X session in thet TTY
    if [ "$display" != "-" ]; then
        # 1st non root display is used if TTY is not matched with the active
        [ "$DISPLAY" == "" ] && DISPLAY="$display"
        # If it is the active TTY we can stop, this is the active X!
        [ "$tty" == "$(cat /sys/class/tty/tty0/active)" ] && DISPLAY="$display";
    fi
done <<< "$(w -hs)"

echo "$DISPLAY"

This checks all login sessions which have X sessions as well. If the tty is also match we can be sure it is the active X session, else we use the 1st one.

This script can be extended to match current user as well if you want.

Solution 5

Next script lists user name and display number for logged in users when the corresponding terminal is active.

w -hs | \
awk -v tty="$(cat /sys/class/tty/tty0/active)" \
    '$2 == tty && $3 != "-" {print $1 FS $3}'

Result:

myuser :0

Share:
42,935

Related videos on Youtube

Skillet
Author by

Skillet

Updated on September 18, 2022

Comments

  • Skillet
    Skillet over 1 year

    I'm using Arch Linux and things are not so easy when you try to discover the current Xorg DISPLAY (not through the env variable).

    Here is a working example:

    $ cat /sys/class/tty/tty0/active
    tty2
    
    who | awk -v term="tty2" '/\(:/ $0 ~ term { gsub(/\(|\)/, "", $0); print $5 }'
    :0
    

    That works in some cases, in others not:

    $ cat /sys/class/tty/tty0/active
    tty3
    
    who | awk -v term="`cat /sys/class/tty/tty0/active`" '/\(:/ $0 ~ term { gsub(/\(|\)/, "", $0); print $5 }'
    NOTHING
    

    Cause:

    $ who
    uzumaki  tty2         2015-05-16 10:50 (:0)
    guest    pts/2        2015-05-16 11:47 (:1)
    uzumaki  tty4         2015-05-16 11:07
    

    The guest user (tty3) had his session lauched using pts (pseudo terminal).

    I'm using gdm and it launches xorg servers without a specific command (not clarifying the display number).

    $ ps au | grep -e Xorg -e vt
    uzumaki    788  1.4  0.9 740464 150672 tty2    Sl+  10:50   5:38 /usr/lib/xorg-server/Xorg vt2 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -nolisten tcp -background none -noreset -keeptty -verbose 3
    guest     1062  0.0  0.1 465748 32344 tty3     Sl+  10:51   0:19 /usr/lib/xorg-server/Xorg vt3 -displayfd 3 -auth /run/user/1002/gdm/Xauthority -nolisten tcp -background none -noreset -keeptty -verbose 3
    

    So the million question is: How to find out the current (in use) XServer DISPLAY number? Current because, as above, we can have multiples servers (multiple users).

    • Bananguin
      Bananguin almost 9 years
      Why are you trying to find out the so called "current" XDISPLAY? What do you mean by "current"? Apparently you have at least two XServer running. Which is current and why?
  • Skillet
    Skillet almost 9 years
    Hi @intelfx, here it didn't work: loginctl list-sessions returns c1, c2 and c3 as SESSIONS. So loginctl show-session -p Display c1 or c2 or even c3 returns always Display=
  • Andrey Tigay
    Andrey Tigay almost 9 years
    @geyslan: Sorry, I've misremembered information which is returned by loginctl list-sessions -- there is no "ACTIVE" column... And, actually, situation turns out to be worse than I thought: starting with 3.16, GDM stopped passing the X11 display number to logind due to a structural rework. Though this may work with other compliant DMs.
  • Skillet
    Skillet almost 9 years
    No problem @intelfx. Thank you for your help anyway.
  • Bananguin
    Bananguin almost 9 years
    This is a very greedy approach and needn't return the correct DISPLAY. You should evaluate all environments and assume the value of DISPLAY which you read most frequently.
  • Bananguin
    Bananguin almost 9 years
    @intelfx: very nice approach. In 1-2 major releases I may come to like this *d stuff. Just to throw in another idea: I once had to match XDisplays to usernames. I build a little something that looks at all incoming TCP connections to the various Xservers and does a majority vote on the users the connecting processes belong to. Works fairly well with modern DEs.
  • Skillet
    Skillet almost 9 years
    @bananguin Given some tty could more than one x server be running in it?
  • Bananguin
    Bananguin almost 9 years
    you are not looking at Xservers, only at environmental variables. We always need to be very careful about what we assume about environmental variables.
  • Skillet
    Skillet almost 9 years
    I see your caution. Do you have some code to suggest (bash)?
  • dirkt
    dirkt over 7 years
    The question is ill-defined. I can easily have a dozen of "active" X-connections (some local, some remote), and I can have all of them in the same shell, on the same controlling tty. I can change DISPLAY at will, several times. You can look for DISPLAY in the environment of processes you are interested in (you didn't say which ones), but that's all you can do.