我有一个简单的需求,即运行一个 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"