当 DISPLAY 未设置时,如何以编程方式查找 DISPLAY 的当前值?(用于 crontab)

当 DISPLAY 未设置时,如何以编程方式查找 DISPLAY 的当前值?(用于 crontab)

我有一个通过 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为在为用户找到的$DISPLAYtty 值中运行的第一个 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

相关内容