我正在使用 Arch Linux,当您尝试发现当前的 Xorg DISPLAY(不是通过 env 变量)时,事情并不那么容易。
这是一个工作示例:
$ cat /sys/class/tty/tty0/active
tty2
who | awk -v term="tty2" '/\(:/ $0 ~ term { gsub(/\(|\)/, "", $0); print $5 }'
:0
这在某些情况下有效,但在其他情况下则无效:
$ cat /sys/class/tty/tty0/active
tty3
who | awk -v term="`cat /sys/class/tty/tty0/active`" '/\(:/ $0 ~ term { gsub(/\(|\)/, "", $0); print $5 }'
NOTHING
原因:
$ 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
来宾用户(tty3)使用 pts(伪终端)启动其会话。
我正在使用 gdm,它无需特定命令即可启动 xorg 服务器(未澄清显示编号)。
$ 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
所以万个问题是:如何找出当前(正在使用的)XServer DISPLAY 数量?当前是因为,如上所述,我们可以拥有多个服务器(多个用户)。
答案1
您可以尝试使用loginctl list-sessions
获取会话列表,然后使用loginctl show-session -p Display -p Active <session ID>
每个会话来获取与当前活动会话关联的 X11 显示编号。
像这样的东西(在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)
这里$TARGET_DISPLAY
是一个数组,因为假设可能有多个活动会话(在多席位系统上)。如果这在您的配置中不可能,您可以将其设为一个简单变量,并break 2
在赋值后添加一条语句以退出两个循环。
然而...
...这不再适用于 GDM,因为在这种情况下 X 服务器已启动里面会话(具有用户权限)并且/usr/bin/gdm-x-session
不会将此信息传达回logind
(由于缺乏相应的 API)。
在其他情况下(当 X 服务器在创建会话之前由 DM 启动时),这很可能会起作用。我不知道还有其他方法,抱歉。
答案2
嗯,目前我的意思是积极的XOrg 服务器的显示。请记住,我们可以运行多个 XOrg 服务器,并且它们可以是多头的,这使得事情更难以操纵。
另一个重要的注意事项是,在某些情况下无法访问 DISPLAY 变量(例如 systemd)。
经过一番讨论后命令行fu,我得到这个结果:
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
此代码片段迭代设置了控制终端并与该进程的终端匹配的所有进程(实际上是它们的 ID)的列表。它检查每个进程的环境中的DISPLAY
变量,并在找到变量后立即满足。找到DISPLAY
变量后,它会停止迭代列表并echo
获取结果。
这将打印运行脚本的活动显示。
答案3
这是在同一主机上运行两个服务器的示例。我曾经startx
启动过它们,正如您从pstree -pl
下面的输出中看到的那样。第一个带有 set 的子进程$DISPLAY
是.xinitrc
:
|-login(698)---zsh(1077)---startx(1359)---xinit(1381)-+-.xinitrc(1386)...
这是命令;如果您有不同的设置,可以.xinitrc
在此处更改为其他设置:
$ 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
这些数字显示每个显示器的空闲时间(以毫秒为单位)。最上面一行显示最近活动(最少空闲)的显示屏。
就其价值而言,其他答案都不适合我。
答案4
这是我基于其他答案的解决方案:
#!/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"
这会检查所有具有 X 会话的登录会话。如果 tty 也匹配,我们可以确定它是活动的 X 会话,否则我们使用第一个。
如果需要,也可以扩展此脚本以匹配当前用户。