Editando Gsettings sem sucesso quando iniciado a partir do cron

6

Eu devo ter um ponto cego, mas não consigo encontrar o que é.

Eu fiz um pequeno script python que remove o VLC do menu de som. Ele funciona perfeitamente de qualquer maneira que eu corri-lo a partir do terminal ou de um lançador ou o que você pode pensar.

O que o script realmente faz é nada mais do que obter as configurações atuais:

gsettings get com.canonical.indicator.sound interested-media-players

edite a lista e defina a lista alterada por:

gsettings set com.canonical.indicator.sound interested-media-players "['newlist']"

Estes comandos são executados por um script python. No entanto, quando executado a partir de um cronjob ( crontab -e ), apenas a parte gsettings - get - funciona, mas não a seção gsettings - set - . Que a seção get funcione bem com o cron, eu verifiquei fazendo o script gravar dados (o original e também o editado) em um arquivo externo.

Não é um problema de python

Para ver se o problema está relacionado ao código python, criei um script bash que aplica uma lista de itens de menu de som alterados. A história é a mesma: o script bash é executado da linha de comando ou de um launcher, não do cron, enquanto qualquer outro comando no mesmo script rodaria bem. Além disso, se eu adicionar qualquer comando no final do script abaixo, ele funciona bem e parece que o script está satisfeito com seu próprio trabalho.

Por que o comando gsettings set não funciona quando iniciado pelo cron?

Este é o script:

#!/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)
    
por Jacob Vlijm 15.06.2014 / 17:32

1 resposta

6

A solução

Descobri que o ponto cego era um buraco no meu conhecimento. A razão para não executar comandos específicos no script python ( gsettings set ) foi porque o cron usa um conjunto muito restrito de variáveis de ambiente.

Para executar um comando gsettings *set* do cron (em geral), é preciso mais do que apenas executá-lo a partir do seu arquivo cron pessoal; a variável de ambiente DBUS_SESSION_BUS_ADDRESS é necessária para a execução correta.

Por razões de conveniência e flexibilidade, resolvi-o, inspirado e baseado nas informações em esta publicação sobre estouro de pilha , criando um script "intermediário" que exporta a variável e chama o script real. O script real edita gsettings . Como (normalmente) um processo herda o ambiente de seu pai, agora o script é executado corretamente.

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

(assumindo que script.py é executável)

Incluindo a variável DBUS_SESSION_BUS_ADDRESS em um script python

Para tornar a edição gsettings possível por um script python, executado pelo cron (e tornar um script intermediário desnecessário), a função abaixo poderia ser incluída no script. Deve ser chamado antes da função gsettings set no script.

#!/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("
#!/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
", "")
    
por Jacob Vlijm 17.06.2014 / 23:09