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?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • 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 08 '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 Quénot Mar 08 '18 at 21:15
  • For the same user, I think it's not necessary to force XAUTHORITY (tested with zenity in cron) – Gilles Quénot Mar 08 '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 08 '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 Quénot Mar 08 '18 at 22:26
  • I can get this with valid XAUTHORITY but differences in network or hostname, not sure why this happens to you. Check https://stackoverflow.com/a/25280523/5369403, try to insert ffff into the cookie. Like: xauth nlist :0 -f $XAUTHORITY | sed -e 's/^..../ffff/' | xauth -f /tmp/mycookie nmerge - and afterwards use XAUTHORITY=/tmp/mycookie – mviereck Mar 08 '18 at 22:40
  • @Gilles: the solution provided in your link require to be root : tr '\0' '\n' < /proc/<PID>/environ and I need to automating fetching this as user and with n > 1 Xorgs instances – Gilles Quénot Mar 08 '18 at 23:56
  • Edited post with the same information – Gilles Quénot Mar 08 '18 at 23:59
  • Uh? No, that thread is about accessing the display of the same user, there's no need to be root. – Gilles 'SO- stop being evil' Mar 09 '18 at 07:20
  • It don't provide a full workable snippet like I does below, and I tried code from that other post with the PID of Xorg, that is run as root (my bad). Moreover, the post is all about remote X display, this is not the case here, it's all local X display – Gilles Quénot Mar 09 '18 at 11:00
  • What should happen if the machine uses several DISPLAYs (not common today, but still done), and the same user is logged in on more than one of them? (This also explains why there is no portable way to do this: You shouldn't be able to display something on the display of some user, even if the same user, without explicit permission). – dirkt Mar 09 '18 at 12:29
  • Good question, I try to deal with this case, and the DISPLAY is correctly detected. I tested it as well. If the user install my project, he knows that some GUI will be displayed in his own session. Check my answer below – Gilles Quénot Mar 09 '18 at 12:48

2 Answers2

7

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.

mviereck
  • 2,467
  • 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 Quénot Mar 08 '18 at 21:28
  • @GillesQuenot I have neither ~/.Xauthority nor /tmp/xauth*. And ps uww $(pidof Xorg) does not give me DISPLAY, sorry. – mviereck Mar 08 '18 at 21:39
  • Wich distro please ? Very interesting – Gilles Quénot Mar 08 '18 at 21:44
  • 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 08 '18 at 21:48
  • 1
    @GillesQuenot I've added a systemctl --user show-environment command. – mviereck Mar 08 '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 Quénot Mar 08 '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. https://unix.stackexchange.com/questions/231152/ https://unix.stackexchange.com/questions/368730/ https://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 09 '18 at 06:14
5

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