Integrating systemctl --user and your Graphical Session
December 28, 2017For those of us nerds who have been running Linux on the desktop for years now, the addition of systemd in recent
releases has opened up some interesting user service management solutions. While not often discussed, systemctl --user
is a per-user systemd service management system which sports most if not all of the features of the parent PID 1
systemd.
One issue I ran into on elementary 0.4 Loki (Ubuntu 16.04) was that the environment of systemctl --user
was pretty
barren:
naftuli@laststand:~$ systemctl --user show-environment
HOME=/home/naftuli
LANG=en_US.UTF-8
LOGNAME=naftuli
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash
USER=naftuli
XDG_RUNTIME_DIR=/run/user/1000
This constitutes the bare minimum of what a user service might need. However, for starting user services
on the desktop, this environment doesn’t have a reference back to the DISPLAY
or anything else about the desktop
session.
I found a workaround for this limitation by defining a script called by the desktop session on login and a user target
called user-graphical-login.target
which other services can depend on.
My script simply imports the current environment and starts the user-graphical-login.target
, allowing other units to
start:
#!/usr/bin/env bash
systemctl --user import-environment
systemctl --user start user-graphical-login.target
Drop this wherever you’d like, and then add it as a startup script in your distribution’s startup applications:
Next, let’s define our target at ~/.config/systemd/user/user-graphical-login.target
:
[Unit]
Description=User Graphical Login
Requires=default.target
After=default.target
Log out, log back in, and then check that the target has been started:
naftuli@laststand:~$ systemctl --user status user-graphical-login.target
● user-graphical-login.target - User Graphical Login
Loaded: loaded (/home/naftuli/.config/systemd/user/user-graphical-login.target; static; vendor preset: enabled)
Active: active since Wed 2017-12-27 11:54:16 PST; 1 day 3h ago
Dec 27 11:54:16 laststand systemd[1938]: Reached target User Graphical Login.
Dec 27 11:54:27 laststand systemd[1938]: Reached target User Graphical Login.
If we now dump the environment from systemd --user
, we should now see a ton of environment variables:
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-4CdgBoOWOy,guid=54269270bb9eccd9b83e0e1f5a43fa10
DEFAULTS_PATH=/usr/share/gconf/pantheon.default.path
DESKTOP_SESSION=pantheon
DISPLAY=:0
EDITOR=vim
GDMSESSION=pantheon
GDM_LANG=en_US
GIO_LAUNCHED_DESKTOP_FILE=/usr/share/applications/org.pantheon.terminal.desktop
GIO_LAUNCHED_DESKTOP_FILE_PID=3930
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GPG_TTY=/dev/pts/4
GSETTINGS_SCHEMA_DIR=/home/naftuli/data
GTK_CSD=1
GTK_MODULES=pantheon-filechooser-module:gail:atk-bridge
HOME=/home/naftuli
LANG=en_US.UTF-8
LANGUAGE=en_US
LESSCLOSE=/usr/bin/lesspipe %s %s
LESSOPEN=| /usr/bin/lesspipe %s
LOGNAME=naftuli
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
MANDATORY_PATH=/usr/share/gconf/pantheon.mandatory.path
PANTHEON_TERMINAL_ID=0
PATH=/home/naftuli/bin:/home/naftuli/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
POWERLINE_COMMAND=powerline
PROMPT_COMMAND=__bp_precmd_invoke_cmd; dbus-send --type=method_call --session --dest=org.pantheon.terminal /org/pantheon/terminal org.pantheon.terminal.ProcessFinished string:$PANTHEON_TERMINAL_ID string:"$(history 1 | cut -c 8-)" >/dev/null 2>&1; __bp_interactive_mode;
PWD=/home/naftuli
QT_ACCESSIBILITY=1
QT_IM_MODULE=ibus
QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1
QT_STYLE_OVERRIDE=gtk
SESSION_MANAGER=local/laststand:@/tmp/.ICE-unix/2023,unix/laststand:/tmp/.ICE-unix/2023
SHELL=/bin/bash
SHLVL=2
SSH_AGENT_PID=2095
SSH_AUTH_SOCK=/home/naftuli/.gnupg/S.gpg-agent.ssh
TERM=screen-256color
TMUX=/tmp/tmux-1000/default,1956,1
TMUX_PANE=%1
USER=naftuli
VTE_VERSION=4205
XAUTHORITY=/home/naftuli/.Xauthority
XDG_CONFIG_DIRS=/etc/xdg/xdg-pantheon:/etc/xdg
XDG_CURRENT_DESKTOP=Pantheon
XDG_DATA_DIRS=/usr/share/pantheon:/usr/local/share/:/usr/share/
XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/naftuli
XDG_MENU_PREFIX=gnome-
XDG_RUNTIME_DIR=/run/user/1000
XDG_SEAT=seat0
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
XDG_SESSION_DESKTOP=pantheon
XDG_SESSION_ID=c2
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
XDG_SESSION_TYPE=x11
XDG_VTNR=7
XMODIFIERS=@im=ibus
_=/bin/systemctl
Now, your user services can start graphical applications and interact with the session.