6

I have a project that needs to detect the DISPLAY in shell () variable to be able to display some stuff on the local machine.

Or a better solution ( ?) to open stuff in non interactive shell without trying to figure out DISPLAY and XAUTHORITY.

I can set DISPLAY=:0 but that will fail if a user uses another session.

As far as I'm not in interactive mode, what I tried (works well, but only as root) is:

strings /proc/$(pidof Xorg)/environ | grep -Eo 'DISPLAY=:[0-9]+(:[0-9])*'

or as user:

ps uww $(pidof Xorg) | grep -oE '[[:blank:]]:[0-9]+(:[0-9])*\b'

But I don't know if it's reliable on any Linux (Unixes?)

Is there a more reliable/portable way?

12
  • 2
    What if there is no X server running on the machine, but X is forwarded from another machine (e.g. using ssh -X)? Mar 8, 2018 at 20:36
  • I try to deal only with local X session, but if you have a magic trick to deal both on local and remote, welcome Mar 8, 2018 at 21:15
  • For the same user, I think it's not necessary to force XAUTHORITY (tested with zenity in cron) Mar 8, 2018 at 22:07
  • The same user may have an additional authentication with xhost Check the output of xhost, remove the entry with xhost -SI:localuser:USERNAME and try again. xhost entries can be given, but do not rely on them.
    – mviereck
    Mar 8, 2018 at 22:10
  • What's strange is that if I force XAUTHORITY to what I fetched from Xorg command or other places, in cron, I get error 'Unable to init server: Could not connect: Connection refused' (with the good DISPLAY and the same user) Mar 8, 2018 at 22:26

2 Answers 2

6

On distributions with init system systemd the output of

systemctl --user show-environment

shows DISPLAY and XAUTHORITY. This is at least true for my debian 9 system with systemd and gdm3 as display manager.

Pitfall: After running startx xterm -- :2 vt2 on tty2 systemctl gave me DISPLAY and XAUTHORITY from the new display; my main display :0 was no longer observably this way.


Other approaches:

At least for XAUTHORITY it is more reliable to parse the output of ps aux | grep Xorg and look for option -auth. In my case it is located at /run/user/1000/gdm/Xauthority and not at ~/.Xauthority.

Pitfalls:

  • There can be more than one Xorg instance.
  • Instead of Xorg there can be Xwayland.
  • Instead of Xorg there can be Xvfb or something else.
  • It may be a remote session without local Xorg at all.

Normally Xorg commands also contain the display number. Unfortunately, mine does not:

/usr/lib/xorg/Xorg vt1 -displayfd 3 -auth /run/user/1000/gdm/Xauthority -background none -noreset -keeptty -verbose 3

-displayfd 3 somehow points to DISPLAY. If looking as root at /proc/$(pidof Xorg)/fd/3 I find

    lrwx------ 1 root root 64 Mär  8 22:45 3 -> socket:[21437]

Though, I don't know how to look for socket 21437. I am sure it points to /tmp/.X11-unix/X0. One approach is lsof +E -aUc Xorg that shows interesting output: many connections containing @/tmp/.X11-unix/X0 and one dbus connection.

A bit dirty: The fd folder also shows me

l-wx------ 1 root root 64 Mär  8 22:45 5 -> /var/log/Xorg.0.log

Xorg.0.log is a clear indication for display :0.


Another approach: notify-send seems to gather DISPLAY and XAUTHORITY with some dbus magic. But I have no clue how. That may be the cleanest and most portable way, if at least a dbus daemon is running.

7
  • Added a w to my ps uw so ps uww, now I have both XAUTHORITY and DISPLAY, it's a good start. I think you have maybe ~/.Xauthority and /tmp/xauth* too Mar 8, 2018 at 21:28
  • 1
    @GillesQuenot It is debian 9. But I assume this is rather special to display manager gdm3 than to debian. I found a hint for -displayfd 3, I'll edit my answer.
    – mviereck
    Mar 8, 2018 at 21:48
  • 1
    @GillesQuenot I've added a systemctl --user show-environment command.
    – mviereck
    Mar 8, 2018 at 23:14
  • 1
    Unfortunately, doesn't work in cron, so doesn't work for non interactive shell: Failed to connect to bus. One solution is to declare DBUS_SESSION_BUS_ADDRESS=xxx before, that is something maybe possible in my case at install time. Just hope that's a stable PATH (mine is unix:path=/run/user/1000/bus) Mar 8, 2018 at 23:21
  • 1
    The premise of the Desktop Bus/systemd design is that any given user's programs only ever talk to one X server, and all talk to that same one. unix.stackexchange.com/questions/231152 unix.stackexchange.com/questions/368730 unix.stackexchange.com/questions/145167 The Desktop Bus people claim that there is a default for obtaining the per-user desktop bus broker's socket, but there are practical problems with that claim.
    – JdeBP
    Mar 9, 2018 at 6:14
4

Final solution not requiring to be root, and accessible from a non-interactive shell in an automated way and more advanced and usable than possible duplicate link provided earlier :

-XAUTHORITY :

ps -u $(id -u) -o pid= |
  xargs -I{} cat /proc/{}/environ 2>/dev/null |
  tr '\0' '\n' |
  grep -m1 '^XAUTHORITY='

- DISPLAY :

ps -u $(id -u) -o pid= |
  xargs -I{} cat /proc/{}/environ 2>/dev/null |
  tr '\0' '\n' |
  grep -m1 '^DISPLAY='

The snippet list all user's pids, iterate over them, then break on the first match

Based on this

0

Not the answer you're looking for? Browse other questions tagged .