2

This question already has an answer here:

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?

marked as duplicate by Gilles, Archemar, elbarna, Timothy Martin, G-Man Mar 10 '18 at 5:51

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    What if there is no X server running on the machine, but X is forwarded from another machine (e.g. using ssh -X)? – Daniel Pryden Mar 8 '18 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 – Gilles Quenot Mar 8 '18 at 21:15
  • For the same user, I think it's not necessary to force XAUTHORITY (tested with zenity in cron) – Gilles Quenot Mar 8 '18 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 '18 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) – Gilles Quenot Mar 8 '18 at 22:26
3

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.

  • 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 – Gilles Quenot Mar 8 '18 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 '18 at 21:48
  • 1
    @GillesQuenot I've added a systemctl --user show-environment command. – mviereck Mar 8 '18 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) – Gilles Quenot Mar 8 '18 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 '18 at 6:14
1

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.