I must have a blind spot, but I cannot find what it is.

I made a small python script that removes VLC from the sound menu. It runs perfectly in any way I run it from the terminal or from a launcher or whatever you can think of.

What the script actually does is nothing more than get the get the current settings:

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

edit the list, and set the changed list by:

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

These commands are executed by a python script,. However, when run from a cronjob (crontab -e) only the gsettings - get - part works, but not the gsettings - set - section. That the get section works fine with cron, I checked by making the script write data (the original as well as the edited) to an external file.

Not a python problem

To see if the problem is related to python code, I created a bash script that applies a changed sound menu items list. The story is the same: the bash script runs fine from the command line or a launcher, not from cron, while any other command in the same script would run fine. Also, if I add any command at the end of the script below, it works fine and it looks like the script is satisfied with its own work.

Why is the gsettings set command not working when initiated from cron?

This is the script:

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(", ", ",")
        "gsettings", "set", "com.canonical.indicator.sound", "interested-media-players",

current_list = read_soundmenu()
for item in current_list:
    if item == "vlc.desktop":

The solution

It turned out the blind spot was a hole in my knowledge. The reason for not running specific commands in the python script (gsettings set) was because cron uses a very restricted set of environment variables.

To run a gsettings *set* command from cron (in general), it takes more than just running it from your personal cron file; the environment variable DBUS_SESSION_BUS_ADDRESS is needed for correct execution.

For reasons of convenience and flexibility, I solved it, inspired by- and based on the information in this post on stack overflow, by creating an "intermediate" script that both exports the variable and calls the actual script. The actual script edits gsettings. Since (normally) a process inherits the environment of its parent, now the script runs fine.


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

(assuming script.py is executable)

Including the DBUS_SESSION_BUS_ADDRESS variable in a python script

To make editing gsettings possible by a python script, run by cron (and make an intermediate script unnecessary) the function below could be included in the script. It should be called before the gsettings set function in the 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("\0", "")
|improve this answer|||||
  • 1
    Great post Jacob. This is very helpfull too for customizing vagrant provisions. – Wtower Feb 3 '16 at 13:57
  • @Wtower I am glad it is of use! – Jacob Vlijm Feb 3 '16 at 14:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.