Редактирование 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", "")