Я сделал небольшой скрипт на 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 - набор - секция. То, что секция get отлично работает с cron, я проверил, заставив скрипт записать данные (как исходные, так и отредактированные) во внешний файл.
Не проблема Python
Чтобы увидеть, связана ли проблема с кодом 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)
решение
оказалось, что мертвая зона была дырой в моем знании. Причина того, чтобы не работать конкретный команды в сценарии (gsettings set
) Python состояли в том, потому что крон использует очень ограниченный набор переменных среды.
Для выполнения gsettings *set*
команда от крона (в целом) это берет больше, чем просто выполнение его из персонального файла крона; переменная среды 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, запущенным кроном (и сделать промежуточный сценарий ненужным), функция ниже могла быть включена в сценарий. Это нужно назвать перед эти 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", "")