我有一个名为的 shell 脚本test.sh
:
#!/bin/sh
touch /home/me/testing.txt
/usr/bin/gsettings set org.gnome.desktop.background picture-uri "file:///home/me/Downloads/apod.jpg"
当我从终端运行它时,
bash test.sh
它运行完美。当我通过 crontab 运行它时,它会执行并
testing.txt
创建文件,但是更改桌面背景的那一行不起作用。(crontab 条目是* * * * * bash /home/me/test.sh
)。当我在终端上单独运行更改背景行时:
/usr/bin/gsettings set org.gnome.desktop.background picture-uri "file:///home/me/Downloads/apod.jpg"
它运行完美。
我无法确定实际问题出在哪里以及为什么 shell 脚本的第二部分在通过 crontab 运行时不起作用。
有人向我建议:
多用户系统中的 cron 作业,每个用户坐在自己的桌面上,都不知道要更改哪一个。
所以也许这就是问题所在。有人能建议我如何解决这个问题吗?我不必使用 crontab,我只想让一些脚本每天运行一次。
我正在使用 Ubuntu 18.04。
编辑:最佳答案这个问题看起来很有希望。我添加了以下几行:
# export DBUS_SESSION_BUS_ADDRESS environment variable
PID=$(pgrep gnome-session)
export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-)
到我的 shell 脚本,但这仍然不起作用,但我不明白自己在做什么,也不知道是否必须以某种方式根据我自己的系统定制这些行。
答案1
是的,该gsettings
命令需要访问您的桌面会话的 D-Bus 会话总线。
我不是完全不确定 Ubuntu 18.04 的架构,但我认为它已经完全基于 systemd,因此这个更简单的版本可能会起作用:
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
如果这没有帮助,那么请让桌面环境将正确的地址存储在 cron 作业可以检索的某个地方:
~/.xprofile
:echo "$DBUS_SESSION_BUS_ADDRESS" > ~/.dbus.env
你的计划任务:
export DBUS_SESSION_BUS_ADDRESS="$(cat ~/.dbus.env)"
无论你选择哪种方法,你都应该确实检查它是否能给出与从图形终端执行相同的结果echo $DBUS_SESSION_BUS_ADDRESS
。(您还可以使用“busctl --user”从终端和 cronjob 测试连接。)
多用户系统中的 cron 作业,每个用户坐在自己的桌面上,都不知道要更改哪一个。
这是有点儿相关,但最初这是关于一个略有不同的情况。它讨论了人们尝试直接使用 X11 应用程序在背景(X 根窗口)上绘制新壁纸的情况,例如“hsetroot”。
这并不是说 cron 作业不知道它们为哪个用户运行;它们知道。问题恰恰相反,X11 显示与用户没有关系 - 如果您只有一个 UID,则无法找到该 UID 的 X11 显示。(事实上,每个用户可能有多个 X11 显示!)
直接在桌面会话内运行的程序从 DISPLAY 环境变量获取此信息,但 cron 作业不是任何桌面会话的一部分,也没有 DISPLAY - 所以是的,cron 作业不知道要连接到哪个 X11 显示器。
但是,就您而言,这不太相关,因为gsettings
它不使用 X11 – 它只需通过 D-Bus 与设置存储服务通信。(您的桌面环境 (GNOME) 自动拉新的壁纸 URL 而不是你的 cronjob 必须将其推送到那里,这样原来的显示问题就消失了。)
因此,它基本上用查找 D-Bus 服务器的问题取代了查找 X 服务器的问题。
在较旧的发行版中,这不会有任何区别,因为 D-Bus 地址是随机生成的,并且与你的 UID 也没有任何关系,所以程序仍然必须预先提供正确的 DBUS_SESSION_BUS_ADDRESS(或者从 DISPLAY 间接获取,这就是为什么有些人认为 D-Bus 需要 DISPLAY)。
您找到的 StackOverflow 帖子对此基本正确,尽管现在略显过时。(但其建议的解决方法pgrep gnome-session
完全忘记了可能存在由不同用户拥有的多个 gnome-session 实例的可能性,因此您确实应该要求 pgrep 也按 UID 进行过滤。)
然而,随着 systemd 向 D-Bus 会话总线(每个用户只有一个)迈进(并将每个用户限制为一个图形会话),情况发生了一些变化。作为其中的一部分,DBUS_SESSION_BUS_ADDRESS 不再不可预测——它始终位于同一位置,仅因 UID 而异,并且能被 cron 任务所知。这就是我上面建议的“/run/user/.../bus”路径。
请注意,在某些 Debian 和 Ubuntu 版本中,通过安装软件包可以选择加入此新架构dbus-user-session
- 如果没有它,桌面环境仍将使用每次随机生成 D-Bus 地址的旧方法。
(除此之外,带有“systemd-logind”的系统做如果有图形会话的 X11 显示,至少使用预先将其创建为图形会话的显示管理器,可以更轻松地确定该 X11 显示。与此同时,Wayland 采用了相同的方法,将显示套接字放在 /run/user 下 - 仍然可能有多个,但至少默认的“wayland-0”很容易从 UID 中找到。)