我有一个通过 cron 运行的脚本来更改桌面壁纸。我可以通过导出 DISPLAY 变量来使其工作。
但我担心的问题是该脚本应该在所有系统上运行。如何在不使用 $DISPLAY 的情况下找到 X 服务器设置的 DISPLAY 值?
那么我如何才能以编程方式找到正确的值DISPLAY
。我只能在 时才能让它工作DISPLAY=:1
。将其设置为":0"
会使脚本退出并显示
No protocol specified
Cannot open display.
答案1
你不能确定。你必须做出假设。
假设您cron
正面临最坏的情况:有多个用户登录,每个用户都在运行多个 X 会话。您必须猜测用户(很简单,我们正在执行他们的 crontab)和该用户的一个 X 会话。
如果我们想假设用户正在从 tty 运行一个且仅一个 X 会话,并获取该会话的$DISPLAY
值,我们可以使用w
:
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
user tty1 16:32 7:15 0.21s 0.19s -zsh
user tty2 :1 15:52 48:13 2:17 0.08s /sbin/upstart
user pts/3 :1 16:19 0.00s 0.66s 0.00s w
例如这里我登录了 tty1、tty2(我在其中运行 X 会话)和 pts/3(我在其中运行命令的终端)。
经过一些解析:
% w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}'
:1
因此,假设以上所有情况:
0 0 * * * DISPLAY=$(w $(id -un) | awk 'NF > 7 && $2 ~ /tty[0-9]+/ {print $3; exit}') command
将cron
执行设置command
为在为用户找到的$DISPLAY
tty 值中运行的第一个 X 会话。$DISPLAY
答案2
有关更详细的讨论,请参阅https://unix.stackexchange.com/questions/17255/is-there-a-command-to-list-all-open-displays-on-a-machine
我将在此简单列出该答案中的相关信息:
似乎有两种简单的方法可以找到系统上运行的 X 服务器实例。
w
:
该w
命令列出所有打开的显示。然后您可以使用awk
筛选出所需的信息。下面的值FROM
是 对应的值DISPLAY
。ashhar@xenon:[/tmp/.X11-unix]
答案3
受到 Ashhar Hasan 的回答的启发,我会使用(在 Ubuntu 23.04 上测试):
export DISPLAY=$(
find /tmp/.X11-unix/ -user $USER -type s -printf "%f" -quit | tr X :
)
通过 UID 进行过滤,即使有多个登录用户,它也能正常工作。
我有一个 X11wrap.sh 脚本,它允许我从系统脚本、cron、at 等运行 X11 应用程序。
#!/bin/sh
set -eu
export DISPLAY=$(
find /tmp/.X11-unix/ -user $USER -type s -printf "%f" -quit | tr X :
)
# For applications that additionally require DBUS.
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus
exec "$@"
有了它,我可以发出以下示例,它将正确获取 X11 系统:
echo X11wrap.sh xeyes | at now