Starting A DBus Session Application from systemd User Mode

6,343

Solution 1

You may find some help in the ArchLinux wiki page which discusses setting the environment for user Units. In particular,

systemctl --user import-environment 

will export all the current environment variables into your systemd user environment. You can provide an explicit list of variables instead. You can check by running

systemctl --user show-environment

before and after. There is also

systemctl --user set-environment MYVAR=myvalue ...
systemctl --user unset-environment MYVAR ...

See the systemctl man page. The wiki also mentions a dbus specific alternative with which I had less success:

dbus-update-activation-environment --systemd --all

Solution 2

My solution takes into account @meuh's solution above and some digging.

Step one is to create a dummy user unit called dbus-environment.service:

[Unit]
Description=Environment Imported Target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true

Next step is to create a Bash script:

#!/bin/bash

systemctl --user import-environment
systemctl --user start dbus-environment.service

Next, add this script to your window manager's startup applications which are guaranteed to run within the DBUS session and the window manager, X, etc.

On session login, the script will be called, importing everything into the systemd user daemon.

Next, for all units depending on these environment variables, simply have them depend on dbus-environment.service:

[Unit]
Description=Duplicity Backup Service
Requires=dbus-environment.service
After=dbus-environment.service

[Service]
Type=oneshot
ExecStart=/home/naftuli/.local/bin/duply home backup

At this point, when this service starts, it is guaranteed to have the environment imported. Perhaps I should be using a target rather than a service, but that exercise will have to wait.

Share:
6,343

Related videos on Youtube

Naftuli Kay
Author by

Naftuli Kay

Updated on September 18, 2022

Comments

  • Naftuli Kay
    Naftuli Kay over 1 year

    I have a simple need to run a systemd user service with access to all of the environment variables provided by the user DBus session. Here's my example unit:

    [Unit]
    Description=Environment Demo
    
    [Service]
    Type=simple
    Environment=DISPLAY=:0
    ExecStart=/bin/bash -c 'env > shell.env.sh'
    Restart=on-failure
    RestartSec=5s
    StandardOutput=journal
    StandardError=journal
    
    [Install]
    WantedBy=default.target
    

    The keys exported are:

    _
    DISPLAY
    HOME
    LANG
    LOGNAME
    MANAGERPID
    PATH
    PWD
    SHELL
    SHLVL
    USER
    XDG_RUNTIME_DIR
    

    This is a far cry from the full list of environment variables present if I launch a desktop application from my tray or from my launcher (I'm on elementary OS Loki aka Ubuntu 16.04 xenial). If I launch my terminal emulator (pantheon-terminal) and I get a sorted list of my environment variables, I get the following:

    _
    DBUS_SESSION_BUS_ADDRESS
    DEFAULTS_PATH
    DESKTOP_SESSION
    DISPLAY
    EDITOR
    GDM_LANG
    GDMSESSION
    GIO_LAUNCHED_DESKTOP_FILE
    GIO_LAUNCHED_DESKTOP_FILE_PID
    GNOME_DESKTOP_SESSION_ID
    GPG_TTY
    GSETTINGS_SCHEMA_DIR
    GTK_CSD
    GTK_MODULES
    HOME
    LANG
    LANGUAGE
    LESSCLOSE
    LESSOPEN
    LOGNAME
    LS_COLORS
    MANDATORY_PATH
    PANTHEON_TERMINAL_ID
    PATH
    PROMPT_COMMAND
    PWD
    QT_ACCESSIBILITY
    QT_IM_MODULE
    QT_LINUX_ACCESSIBILITY_ALWAYS_ON
    QT_STYLE_OVERRIDE
    SESSION_MANAGER
    SHELL
    SHLVL
    SSH_AGENT_PID
    SSH_AUTH_SOCK
    TERM
    USER
    VTE_VERSION
    XAUTHORITY
    XDG_CONFIG_DIRS
    XDG_CURRENT_DESKTOP
    XDG_DATA_DIRS
    XDG_GREETER_DATA_DIR
    XDG_MENU_PREFIX
    XDG_RUNTIME_DIR
    XDG_SEAT
    XDG_SEAT_PATH
    XDG_SESSION_DESKTOP
    XDG_SESSION_ID
    XDG_SESSION_PATH
    XDG_SESSION_TYPE
    XDG_VTNR
    XMODIFIERS
    

    To make things more clear:

    diff --git a/systemd-user.env.txt b/pantheon-terminal.env.txt
    index c684056..f6d0685 100644
    --- a/systemd-user.env.txt
    +++ b/pantheon-terminal.env.txt
    @@ -1,12 +1,54 @@
     _
    +DBUS_SESSION_BUS_ADDRESS
    +DEFAULTS_PATH
    +DESKTOP_SESSION
     DISPLAY
    +EDITOR
    +GDM_LANG
    +GDMSESSION
    +GIO_LAUNCHED_DESKTOP_FILE
    +GIO_LAUNCHED_DESKTOP_FILE_PID
    +GNOME_DESKTOP_SESSION_ID
    +GPG_TTY
    +GSETTINGS_SCHEMA_DIR
    +GTK_CSD
    +GTK_MODULES
     HOME
     LANG
    +LANGUAGE
    +LESSCLOSE
    +LESSOPEN
     LOGNAME
    -MANAGERPID
    +LS_COLORS
    +MANDATORY_PATH
    +PANTHEON_TERMINAL_ID
     PATH
    +PROMPT_COMMAND
     PWD
    +QT_ACCESSIBILITY
    +QT_IM_MODULE
    +QT_LINUX_ACCESSIBILITY_ALWAYS_ON
    +QT_STYLE_OVERRIDE
    +SESSION_MANAGER
     SHELL
     SHLVL
    +SSH_AGENT_PID
    +SSH_AUTH_SOCK
    +TERM
     USER
    +VTE_VERSION
    +XAUTHORITY
    +XDG_CONFIG_DIRS
    +XDG_CURRENT_DESKTOP
    +XDG_DATA_DIRS
    +XDG_GREETER_DATA_DIR
    +XDG_MENU_PREFIX
     XDG_RUNTIME_DIR
    +XDG_SEAT
    +XDG_SEAT_PATH
    +XDG_SESSION_DESKTOP
    +XDG_SESSION_ID
    +XDG_SESSION_PATH
    +XDG_SESSION_TYPE
    +XDG_VTNR
    +XMODIFIERS
    

    There are somewhere around 30 more environment variables when starting something this way.


    My use case is this: I want to be able to start processes with a full environment like in the context of launching my terminal application.

    How can I expose a full(er) environment to my systemd user daemons?

  • Jack O'Connor
    Jack O'Connor over 6 years
    OP might also want to look at ~/.config/environment.d. See unix.stackexchange.com/a/403196/23305.
  • Naftuli Kay
    Naftuli Kay almost 6 years
    That would not solve it. The current execution context is systemd, which doesn't have the display manager environment variables. Executing a shell will not have it automatically inherit these environment variables. You need something that is guaranteed to inherit these variables, so a normal shell won't have them.
  • Robin
    Robin almost 6 years
    Thanks! I am a newbie. Still trying to understand systemd. I am actually also stuck in a similar situation where in I would like to import all environment variable available to the user to the system service daemon.. There is no possibility for me to use a script to import these variables. Have you come across another solution so that all the variables which have been set for the users becomes visible to service daemon? Thanks!
  • Naftuli Kay
    Naftuli Kay almost 6 years
    dbus-launch might be able to do something. I was originally crawling the /proc/PID/env of the dbus session to get its address and then call dbus-launch