Iniciando um aplicativo de sessão DBus no modo de usuário systemd

Iniciando um aplicativo de sessão DBus no modo de usuário systemd

Eu tenho uma necessidade simples de executar um serviço de usuário systemd com acesso a todas as variáveis ​​de ambiente fornecidas pela sessão DBus do usuário. Aqui está minha unidade de exemplo:

[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

As chaves exportadas são:

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

Isso está muito longe da lista completa de variáveis ​​de ambiente presentes se eu iniciar um aplicativo de desktop da minha bandeja ou do meu inicializador (estou no sistema operacional elementar Loki, também conhecido como Ubuntu 16.04 xenial). Se eu iniciar meu emulador de terminal ( pantheon-terminal) e obtiver uma lista ordenada de minhas variáveis ​​de ambiente, obtenho o seguinte:

_
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

Para deixar as coisas mais claras:

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

Existem cerca de mais 30 variáveis ​​de ambiente ao iniciar algo dessa maneira.


Meu caso de uso é este: quero poder iniciar processos com um ambiente completo, como no contexto de inicialização do meu aplicativo de terminal.

Como posso expor um ambiente completo aos meus daemons de usuário do systemd?

Responder1

Você pode encontrar alguma ajuda noPágina wiki do ArchLinuxque discute a configuração do ambiente para unidades de usuário. Em particular,

systemctl --user import-environment 

exportará todas as variáveis ​​de ambiente atuais para o ambiente de usuário do systemd. Você pode fornecer uma lista explícita de variáveis. Você pode verificar executando

systemctl --user show-environment

antes e depois. Há também

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

Veja a systemctlpágina de manual. O wiki também menciona uma alternativa específica do dbus com a qual tive menos sucesso:

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

Responder2

Minha solução leva em consideração a solução do @meuh acima e algumas pesquisas.

O primeiro passo é criar uma unidade de usuário fictícia chamada dbus-environment.service:

[Unit]
Description=Environment Imported Target

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

O próximo passo é criar um script Bash:

#!/bin/bash

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

Em seguida, adicione este script aos aplicativos de inicialização do seu gerenciador de janelas que têm garantia de execução na sessão DBUS e no gerenciador de janelas, X, etc.

No login da sessão, o script será chamado, importando tudo para o daemon do usuário systemd.

Em seguida, para todas as unidades que dependem dessas variáveis ​​de ambiente, basta fazer com que elas dependam de 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

Neste ponto, ao iniciar este serviço, é garantido que o ambiente será importado. Talvez eu devesse usar um alvo em vez de um serviço, mas esse exercício terá de esperar.

Responder3

@Naftuli: Não teria sido melhor usar algo assim em todos os arquivos da sua unidade de serviços?

ExecStartPre=\usr\bin\sh -c "systemctl --user import-environment"

informação relacionada