gsettings 的奇怪行为使用 cron 设置了一个新的 desktop.background

Weird behavior of gsettings set a new desktop.background with cron

我想每 5 分钟更换一次桌面背景。我在 ubuntu,这项工作有效地改变了我的背景:

gsettings set org.gnome.desktop.background picture-uri "file:/img.jpg"

我可以从 python 脚本启动它,它会从特定目录中选择随机图像。我把脚本放在这里,即使我不确定它是否与这里相关

import os
import subprocess as sub
import random
files = [f for f in os.listdir('/usr/share/rwallpaper')]
rando = random.randint(0, (len(files) - 1))
cmd = ["gsettings", "set", "org.gnome.desktop.background", "picture-uri"]
wallpaper = "\"file:/usr/share/rwallpaper/" + files[rando] + "\""
cmd.append(wallpaper)
print(" ".join(cmd)) #to remove after
sub.run(cmd)

这也行。所以现在我想使用 cron 定期执行我的 python 代码

$ sudo crontab -e
*/5 * * * * python3 /usr/local/cronwal/cronwal.py

而且它不起作用。我在某处看到这可能是用户环境问题,所以我尝试用

之类的东西更改上面的执行
*/5 * * * * sudo -u "me" python3 /usr/local/cronwal/cronwal.py
*/5 * * * * su me  -c "python3 /usr/local/cronwal/cronwal.py"

不起作用。需要明确的是,在 root shell 中,原始命令(我的 post 顶部的第一个 gsetting 命令)或这两个也不起作用,这不是 cron 问题。

所以,我决定使用 crontab 作为我的用户。可能是 su/sudo

无法解决的用户相关问题

我试过了

$crontab -u me -e #in a shell run by "me"
*/5 * * * * python3 /usr/local/cronwal/cronwal.py 

而且它不起作用。更确切地说,我可以在 cron 服务状态中看到

févr. 14 18:05:01 florent-NB50TZ CRON[56843]: pam_unix(cron:session): session opened for user root by (uid=0)
févr. 14 18:05:01 florent-NB50TZ CRON[56844]: pam_unix(cron:session): session opened for user florent by (uid=0)
févr. 14 18:05:01 florent-NB50TZ CRON[56843]: pam_unix(cron:session): session closed for user root
févr. 14 18:05:01 florent-NB50TZ CRON[56849]: (florent) CMD (python3 /usr/local/cronwal/cronwal.py )
févr. 14 18:05:01 florent-NB50TZ CRON[56844]: pam_unix(cron:session): session closed for user florent

(我撒谎了,“我”是 florent)所以,正如这行

(florent) CMD (python3 /usr/local/cronwal/cronwal.py )

暗示,我 运行 脚本是 florent,所以它应该能正常工作,对吧? 但不是。即使脚本 运行 和我的 florent shell 工作,cron 也不会工作。

python3 /usr/local/cronwal/cronwal.py
#change of background

**编辑:**我确实更改了 crontab 中的行,因此我可以获得反馈。我确实删除了带有选项 MAILTO="" 的邮件,因此我需要以其他方式获得反馈。

*/5 * * * * python3 /usr/local/cronwal/cronwal.py >> /home/florent/cronwal.log 2>>/home/florent/cronwal.log

正如我所想,没有错误输出。我在日志中只有print(" ".join(cmd))

只是一个猜测,但也许 gsettings 需要您的显示服务器设置,只需让您的用户 crontab 看起来像这样:

DISPLAY=:0
*/5 * * * * python3 /usr/local/cronwal/cronwal.py

对于错误的调用,您应该在发给其 crontab 用户的电子邮件中看到一个错误,如果您配置了本地生成的发给不合格用户的邮件,这可能会告诉您未设置显示(尝试 echo . | mail -s testing florent 进行测试,但您需要安装 bsd-mailx 之类的软件包才能进行测试)。 Cron 将标准错误和输出邮件发送给用户 运行 crontab。

所有 X 程序都需要知道显示服务器以用于对其进行操作的操作。您可以阅读 X(7) 手册页了解详细信息。通常在 X 中使用终端时,已经设置了这个环境变量,但在你的 crontab 中你需要提供它。如果您使用的不是 :0,您可以在相关 X 环境中的 shell 中使用 printenv DISPLAY 检查它(顺便说一句 :0:0.0).

除了$DISPLAY你可能还需要设置$DBUS_SESSION_BUS_ADDRESS环境,因为gsettings使用的是dbus(在没有设置DISPLAY的时候发现,报错说无法自动启动D-公共汽车);你可以试试:

DISPLAY=:0
*/5 * * * * eval $(ps -ww -p $(pgrep gnome-session) -o cmd= e | fmt -1 | grep DBUS_SESSION_BUS_ADDRESS) python3 /usr/local/cronwal/cronwal.py

这从 crontab 调用程序拥有的 gnome-session 进程的环境中获取会话地址,并将其设置在您的 python3 进程的环境中,允许分叉 gsettings通过会话总线进行通信的命令。

您可以使用 printenv 检查您的终端中是否设置了 DBUS_SESSION_BUS_ADDRESS 并复制它,如果上面有语法错误(我无法测试),但它不会在下一个 gnome 会话当然如果你像那样硬编码,你每次都必须改变它:

DISPLAY=:0
*/5 * * * * DBUS_SESSION_BUS_ADDRESS="whatever printenv says" python3 /usr/local/cronwal/cronwal.py