Find out the active XOrg Server DISPLAY number (from outside)

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
It's useful when you cannot access your env (systemd) or the process DISPLAY variable is not set. Perhaps also when you have a multi-head/user configuration.
Sample Output
:0

1
By: geyslan
2015-05-18 20:01:20

What Others Think

echo $DISPLAY :0.0
knoppix5 · 174 weeks and 6 days ago
The above method is useful when you cannot access your env (systemd) or the process DISPLAY variable is not set Perhaps also when you have a multi-head/user configuration. So echo $DISPLAY isn't an solution. o/
geyslan · 174 weeks and 6 days ago
My fault. I didn't read the description. I'll vote up to expiate ;)
knoppix5 · 174 weeks and 6 days ago
Hmm... OK I understand. Getting the DISPLAY variable from *outside*. Unfortunately the command is awful. You parse /sys/class/tty/tty0/active for the tty on which X is running. X=$(cat /sys/class/tty/tty0/active) then you find all matching processes Y=$(pgrep -t $X) then you search each process's environment for DISPLAY grep -z DISPLAY /proc/$Y/environ That seems simple: for i in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do grep -z DISPLAY /proc/$i/environ; done | cut -d= -f2 :0 That's 111 characters rather than 243 and no ugly parsing of ps :-)
flatcap · 174 weeks and 6 days ago
@knoppix5, np. @flatcap, yeah, your version is a lot more clean. I didn' t know the -t option in pgrep. Well, in my environment it doesn't works very well: for i in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do grep -z DISPLAY /proc/$i/environ; done | cut -d= -f2 grep: /proc/20358/environ: Permission denied :0DISPLAY So I propose this (164 chars): for p in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do d=$(grep -z DISPLAY= /proc/$p/environ | cut -d= -f2 2>/dev/null); [[ $d != "" ]] && break; done; echo $d
geyslan · 174 weeks and 6 days ago
If you agree, I'll edit it. Or can we shrink it yet? o/
geyslan · 174 weeks and 6 days ago
> I didn' t know the -t option in pgrep @geyslan: I had to look it up, but that was my first guess :-) So grep's complaining. There must be some short-lived processes on the same tty. We only need to mask the error and then let 'cut' do its work on the result of the 'for' loop: (I see a subtle change to your command adding = to the DISPLAY. Good idea, let's be even *more* specific) ... do grep -z '^DISPLAY=' /proc/$p/environ 2> /dev/null; done | ... Now we can drop that 'if' clause. for p in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do grep -z '^DISPLAY=' /proc/$p/environ 2>/dev/null; done | cut -d= -f2 Let me know if that works OK. I'm off to experiment with replacing grep/cut with sed :-)
flatcap · 174 weeks and 6 days ago
@flatcap: good idea the regex ^. Without the if clause, it iterates and show part of the next process env. Let's see: for p in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do grep -z '^DISPLAY=' /proc/$p/environ 2>/dev/null; done | cut -d= -f2 :0DISPLAY A better example without the cut: for p in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do grep -z '^DISPLAY=' /proc/$p/environ 2>/dev/null; done DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0DISPLAY=:0 The loop goes ahead. That was the reason for the $d assignment and condition && break.
geyslan · 174 weeks and 6 days ago
It's a few characters longer, but one command shorter: for p in $(pgrep -t $(cat /sys/class/tty/tty0/active)); do sed -nz '/^DISPLAY=/{s/.*=\(.*\)/\1\n/;p}' /proc/$p/environ 2>/dev/null; done . Run sed on FILE. Don't print (-n) by default, the null-terminated (-z) lines. Search for REGEX, then run two commands on the matches sed -nz '/REGEX/{CMD1;CMD2}' FILE . Match lines '^DISPLAY=' Replace 'DISPLAY=XYZ' with 'XYZ\n' Finally 'p' print the result.
flatcap · 174 weeks and 6 days ago
I see. Because of the null-termination all the lines are getting concatenated. The 'sed' version might be better. I don't have a multi-head setup to test, but I cat'ed lots of environ files together and it looks ok.
flatcap · 174 weeks and 6 days ago
Tested. Works, but it echo from each pid one display. We only need one once they will be the same for tty. In that case the first found. I do prefer awk instead sed. :) So, if to be one command shorter I'll go with awk: 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); [[ $d != "" ]] && break; done; echo $d awk is more clear to me than the slashes hell.
geyslan · 174 weeks and 6 days ago
Tested. Works, but it echo from each pid one display. We only need one once they will be the same for tty. In that case the first found. I do prefer awk instead sed. :) So, if to be one command shorter I'll go with awk: 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); [[ $d != "" ]] && break; done; echo $d awk is more clear to me than the slashes hell.
geyslan · 174 weeks and 6 days ago
OK, last suggestion (I promise)... Simplify the test to: ... [ -n "$d" ] && break
flatcap · 174 weeks and 6 days ago
Oh, yeah. Thank you very much, @flatcap.
geyslan · 174 weeks and 6 days ago
Started with 244 chars: ps u | awk -v tty=$(cat /sys/class/tty/tty0/active) '$0 ~ tty {print $2}' | while read pid && [[ "$d" == "" ]]; do d="$(awk -v RS='\0' -F= '$1=="DISPLAY" {print $2}' /proc/$pid/environ)"; if [ "$d" != "" ]; then echo "$d"; fi; done 2>/dev/null Ended with 165: 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
geyslan · 174 weeks and 6 days ago
Any time :-)
flatcap · 174 weeks and 6 days ago

What do you think?

Any thoughts on this command? Does it work on your machine? Can you do the same thing with only 14 characters?

You must be signed in to comment.

What's this?

commandlinefu.com is the place to record those command-line gems that you return to again and again. That way others can gain from your CLI wisdom and you from theirs too. All commands can be commented on, discussed and voted up or down.

Share Your Commands



Stay in the loop…

Follow the Tweets.

Every new command is wrapped in a tweet and posted to Twitter. Following the stream is a great way of staying abreast of the latest commands. For the more discerning, there are Twitter accounts for commands that get a minimum of 3 and 10 votes - that way only the great commands get tweeted.

» http://twitter.com/commandlinefu
» http://twitter.com/commandlinefu3
» http://twitter.com/commandlinefu10

Subscribe to the feeds.

Use your favourite RSS aggregator to stay in touch with the latest commands. There are feeds mirroring the 3 Twitter streams as well as for virtually every other subset (users, tags, functions,…):

Subscribe to the feed for: