Редактирование Gsettings безуспешно при запуске из cron

У меня должно быть слепое пятно, но я не могу найти, что это такое.

Я сделал небольшой скрипт на 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 - part, но не секция 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)

1 ответ

Решение

Решение

Оказалось, что слепое пятно было дырой в моих знаниях. Причина не запуска определенных команд в скрипте Python (gsettings set) потому что cron использует очень ограниченный набор переменных окружения.

Чтобы запустить gsettings *set* команда от cron (в общем), это больше, чем просто запуск из личного файла cron; переменная окружения DBUS_SESSION_BUS_ADDRESS необходима для правильного выполнения.

По соображениям удобства и гибкости я решил эту проблему, основываясь на информации из этого поста о переполнении стека и основываясь на ней, создав "промежуточный" скрипт, который одновременно экспортирует переменную и вызывает фактический скрипт. Фактические правки скрипта 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 является исполняемым файлом)

Включение переменной DBUS_SESSION_BUS_ADDRESS в скрипт Python

Сделать редактирование gsettings возможно через скрипт на python, запускается 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", "")
Другие вопросы по тегам