从cron启动时编辑Gsettings不成功

我必须有一个盲点,但我找不到它是什么。

我做了一个小的python脚本,从声音菜单中删除了VLC。 它以任何方式运行,从终端或发射器或任何你能想到的任何东西运行它。

脚本实际上做的只不过是获取当前设置:

gsettings get com.canonical.indicator.sound interested-media-players 

编辑列表,并通过以下方式设置更改的列表:

 gsettings set com.canonical.indicator.sound interested-media-players "['newlist']" 

这些命令由python脚本执行。 但是, 当从cronjobcrontab -e运行时,只有gsettings – get – part可以工作,而不是 gsettings – set – section。 get部分与cron一起正常工作,我通过使脚本将数据(原始文件和编辑的数据)写入外部文件来检查。

不是python问题

为了查看问题是否与python代码有关,我创建了一个应用更改的声音菜单项列表的bash脚本。 故事是一样的:bash脚本从命令行或启动器运行良好,而不是从cron运行,而同一脚本中的任何其他命令都可以正常运行。 此外,如果我在下面的脚本末尾添加任何命令,它工作正常,看起来脚本对自己的工作感到满意。

为什么从cron启动时gsettings set命令不起作用?

这是脚本:

 #!/usr/bin/python3 import subprocess def read_soundmenu(): # read the current launcher contents get_menuitems = subprocess.Popen([ "gsettings", "get", "com.canonical.indicator.sound", "interested-media-players" ], stdout=subprocess.PIPE) return eval((get_menuitems.communicate()[0].decode("utf-8"))) def set_current_menu(current_list): # this takes no effect from cron # preparing subprocess command string current_list = str(current_list).replace(", ", ",") subprocess.Popen([ "gsettings", "set", "com.canonical.indicator.sound", "interested-media-players", current_list, ]) current_list = read_soundmenu() for item in current_list: if item == "vlc.desktop": current_list.remove(item) set_current_menu(current_list) 

解决方案

事实certificate,盲点是我所知道的一个漏洞。 不在python脚本( gsettings set )中运行特定命令的原因是因为cron使用了一组非常有限的环境变量。

要从cron(通常)运行gsettings *set*命令,它需要的不仅仅是从您的个人cron文件运行它; 正确执行需要环境变量DBUS_SESSION_BUS_ADDRESS

出于方便和灵活性的原因,我通过创建一个“中间”脚本来启发变量并调用实际脚本,并且基于此post中有关堆栈溢出的信息,解决了它。 实际的脚本编辑gsettings 。 由于(通常)进程inheritance其父进程的环境,因此脚本运行正常。

 #!/bin/bash PID=$(pgrep gnome-session) export DBUS_SESSION_BUS_ADDRESS=$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$PID/environ|cut -d= -f2-);/path/to/script.py 

(假设script.py是可执行的)

在python脚本中包含DBUS_SESSION_BUS_ADDRESS变量

要通过python脚本进行编辑gsettings ,由cron运行(并且不需要使用中间脚本),下面的函数可以包含在脚本中。 它应该在脚本中的gsettings set函数之前调用。

 #!/usr/bin/env python3 import os import subprocess def set_envir(): pid = subprocess.check_output(["pgrep", "gnome-session"]).decode("utf-8").strip() cmd = "grep -z DBUS_SESSION_BUS_ADDRESS /proc/"+pid+"/environ|cut -d= -f2-" os.environ["DBUS_SESSION_BUS_ADDRESS"] = subprocess.check_output( ['/bin/bash', '-c', cmd]).decode("utf-8").strip().replace("\0", "")