從 systemd 使用者模式啟動 DBus 會話應用程式

從 systemd 使用者模式啟動 DBus 會話應用程式

我有一個簡單的需求,就是執行一個 systemd 使用者服務,並且可以存取使用者 DBus 會話提供的所有環境變數。這是我的範例單元:

[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

導出的密鑰是:

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

如果我從托盤或啟動器啟動桌面應用程式(我使用的是Elementary OS Loki,又名Ubuntu 16.04 xenial),那麼這與存在的環境變數的完整清單相去甚遠。如果我啟動終端模擬器 ( pantheon-terminal) 並且獲得環境變數的排序列表,我會得到以下內容:

_
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

為了讓事情更清楚:

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

以這種方式開始時,大約還有 30 個以上的環境變數。


我的用例是這樣的:我希望能夠在完整的環境中啟動進程,就像在啟動終端應用程式的上下文中一樣。

如何向我的 systemd 使用者守護程式公開完整的(呃)環境?

答案1

您可能會在以下位置找到一些幫助ArchLinux 維基頁面其中討論了為用戶單位設定環境。尤其,

systemctl --user import-environment 

會將所有目前環境變數匯出到您的 systemd 使用者環境中。您可以改為提供顯式變數清單。您可以透過運行來檢查

systemctl --user show-environment

之前和之後。還有

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

請參閱systemctl手冊頁。 wiki 也提到了一個 dbus 特定的替代方案,但我的成功率較低:

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

答案2

我的解決方案考慮了上面@meuh 的解決方案和一些挖掘。

第一步是建立一個名為 的虛擬使用者單元dbus-environment.service

[Unit]
Description=Environment Imported Target

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

下一步是建立 Bash 腳本:

#!/bin/bash

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

接下來,將此腳本新增至視窗管理器的啟動應用程式中,這些應用程式保證在 DBUS 會話和視窗管理器、X 等中執行。

在會話登入時,將呼叫該腳本,將所有內容匯入 systemd 使用者守護程式。

接下來,對於依賴這些環境變數的所有單元,只需讓它們依賴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

至此,當這個服務啟動時,就確保了環境的導入。也許我應該使用目標而不是服務,但是這個練習必須等待。

答案3

@Naftuli:在所有服務單元檔案中使用類似的東西不是更好嗎?

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

相關內容