我一定有一个盲点,但我找不到它是什么。
我制作了一个小的 python 脚本,可以从声音菜单中删除 VLC。它以我从终端或启动器或您能想到的任何方式运行它的任何方式完美运行。
脚本实际上所做的无非是获取当前设置:
gsettings get com.canonical.indicator.sound interested-media-players
编辑列表,并通过以下方式设置更改的列表:
gsettings set com.canonical.indicator.sound interested-media-players "['newlist']"
这些命令由 python 脚本执行。但是,当从 cronjob ( crontab -e
) 运行时,只有 gsettings - get -部分有效,而gsettings - set -部分无效。get部分与cron 一起工作正常,我通过让脚本将数据(原始数据和编辑后的数据)写入外部文件来检查。
不是蟒蛇问题
为了查看问题是否与 python 代码有关,我创建了一个应用更改后的声音菜单项列表的 bash 脚本。故事是一样的:bash 脚本从命令行或启动器运行良好,而不是从 cron 运行,而同一脚本中的任何其他命令都可以运行良好。此外,如果我在下面的脚本末尾添加任何命令,它工作正常,看起来脚本对自己的工作感到满意。
为什么 gsettings set命令在从 cron 启动时不起作用?
这是脚本:
#!/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)
解决方案
事实证明,盲点是我知识上的一个漏洞。不在python 脚本 ( ) 中运行特定
gsettings set
命令的原因是 cron 使用一组非常受限的环境变量。要从 cron(一般情况下)运行
gsettings *set*
命令,不仅仅需要从您的个人 cron 文件运行它;正确执行需要环境变量DBUS_SESSION_BUS_ADDRESS 。出于方便和灵活的原因,我解决了这个问题,并基于这篇关于堆栈溢出的帖子中的信息,通过创建一个既导出变量又调用实际脚本的“中间”脚本。实际脚本编辑
gsettings
. 由于(通常)进程继承其父进程的环境,现在脚本运行良好。(假设 script.py 是可执行的)
在 python 脚本中包含 DBUS_SESSION_BUS_ADDRESS 变量
为了
gsettings
通过 python 脚本进行编辑,由 cron 运行(并且不需要中间脚本),脚本中可以包含以下函数。它应该gsettings set
在脚本中的函数之前调用。