从 cron 启动时编辑 Gsettings 失败

从 cron 启动时编辑 Gsettings 失败

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

我编写了一个小型 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- 得到 -部分工作正常,但是不是gsettings (设置)- 放 -部分。得到部分与 cron 配合良好,我通过让脚本将数据(原始数据和编辑数据)写入外部文件进行了检查。

不是 Python 问题

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

为什么 gsettings从 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)

答案1

解决方案

原来盲点是我知识上的一个漏洞。不跑步的原因具体的python 脚本(gsettings set)中的命令是因为 cron 使用了一组非常受限制的环境变量。

要从 cron运行gsettings *set*命令(一般来说),不仅仅需要从个人 cron 文件运行它;环境变量DBUS_SESSION_BUS_ADDRESS是正确执行所必需的。

为了方便和灵活,我根据以下信息解决了这个问题:这篇关于 stack overflow 的帖子,通过创建一个“中间”脚本,该脚本既导出变量又调用实际脚本。实际脚本编辑gsettings。由于(通常)进程继承了其父进程的环境,因此现在脚本可以正常运行。

#!/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 变量

为了能够通过 cron 运行的 Python 脚本进行编辑gsettings(并且不需要中间脚本),可以将以下函数包含在脚本中。它应该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", "")

相关内容