由于“无法获取 D-bus 连接:权限被拒绝”而无法使用“systemctl --user”

由于“无法获取 D-bus 连接:权限被拒绝”而无法使用“systemctl --user”

我正在尝试设置用户级服务,使用这个答案回答类似的问题。我已经创建了所需的文件并重新启动。

我正在取得进展,因为现在我收到的是“无法获取 D 总线连接:权限被拒绝”,而之前是“无法获取 D 总线连接:连接被拒绝”,但我很困惑,因为我不知道它试图访问什么对象(文件?套接字?),所以甚至无法检查当前权限。有什么想法吗?

到目前为止我已经添加了:

loginctl enable-linger userservice

/usr/lib/systemd/user/dbus.service (-rw-r--r-- root root)

[Unit]
Description=D-Bus User Message Bus
Requires=dbus.socket

[Service]
ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation
ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig

[Install]
Also=dbus.socket

/usr/lib/systemd/user/dbus.socket (-rw-r--r-- root root)

[Unit]
Description=D-Bus User Message Bus Socket

[Socket]
ListenStream=%t/bus
ExecStartPost=-/bin/systemctl --user set-environment DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus

[Install]
WantedBy=sockets.target
Also=dbus.service

/home/用户服务/.config/systemd/user/用户服务.service

[Unit]
Description=Test user-level service

[Service]
Type=dbus
BusName=com.wtf.service
ExecStart=/home/userservice/userservice.py
Restart=on-failure

[Install]
WantedBy=default.target

没有添加其他地方的任何链接...

使其失败:

systemctl --user status

编辑2018-10-25:

添加export XDG_RUNTIME_DIR=/run/user/$(id -u).bashrc。变量已设置,现在我得到:Failed to get D-us connection: no such file or directory。奇怪的是, 和 都没有man systemctl提到systemctl --help--user选项,而两者都提到--system并指定这是默认值(那么其他选项是什么)。

使用带有 SELinux 的 RHEL 7.4(systemd 219如所报告systemctl --version)。

答案1

我注意到 Tableau 服务器使用 --user systemd 服务 - 他们甚至在他们的文档中对此有说明: https://help.tableau.com/current/server-linux/en-us/systemd_user_service_error.htm

systemd 用户服务不像常规的 systemd 进程管理器那样常用。Red Hat 在 RHEL 7 中禁用了 systemd 用户服务(因此所有来自 RHEL 的发行版,如 CentOS、Oracle Linux 7、Amazon Linux 2)。但是,RedHat 向 Tableau 保证,只要重新启用该服务,就可以运行 systemd 用户服务。

他们是如何做到的(例如,用户 ID 为 29575)

# cat /etc/systemd/system/[email protected]
[Unit]
Description=User Manager for UID %i
After=systemd-user-sessions.service
# These are present in the RHEL8 version of this file except that the unit is Requires, not Wants.
# It's listed as Wants here so that if this file is used in a RHEL7 settings, it will not fail.
# If a user upgrades from RHEL7 to RHEL8, this unit file will continue to work until it's
# deleted the next time they upgrade Tableau Server itself.
After=user-runtime-dir@%i.service
Wants=user-runtime-dir@%i.service

[Service]
LimitNOFILE=infinity
LimitNPROC=infinity
User=%i
PAMName=systemd-user
Type=notify
# PermissionsStartOnly is deprecated and will be removed in future versions of systemd
# This is required for all systemd versions prior to version 231
PermissionsStartOnly=true
ExecStartPre=/bin/loginctl enable-linger %i
ExecStart=-/lib/systemd/systemd --user
Slice=user-%i.slice
KillMode=mixed
Delegate=yes
TasksMax=infinity
Restart=always
RestartSec=15

[Install]
WantedBy=default.target

创建该文件后:

systemctl daemon-reload
systemctl enable [email protected]
systemctl start [email protected]

并且您需要通过 bashrc 或类似方式在该用户的环境中设置 XDG_RUNTIME_DIR:

[ -z "${XDG_RUNTIME_DIR}" ] && export XDG_RUNTIME_DIR=/run/user/$(id -ru)

我已经在最近的 RHEL 7.8 上进行了测试并且它可以按预期运行,执行此操作后我可以以我的用户身份运行“systemctl --user status”。

答案2

因此,存在一个长期存在的问题,即XDG_RUNTIME_DIR当用户登录时,环境变量无法正确设置,或者根本无法设置,因此无法访问用户 D-Bus。当用户通过本地图形控制台以外的其他方法登录时,就会发生这种情况。

您可以通过向用户添加以下内容来解决此问题$HOME/.bashrc

export XDG_RUNTIME_DIR=/run/user/$(id -u)

然后注销并重新登录。

答案3

您应该了解 PAM 的工作原理。

如果你使用以下任一方式登录系统

  1. 图形会话
  2. 在终端上登录(用户名和密码)
  3. 远程控制

然后 PAM 机制将调用pam_systemd,这将设置所有需要使用的钩子systemctl;如果您使用sudo或切换用户su,则不会发生这种情况。

这是故意的,明白吗 https://github.com/systemd/systemd/issues/7451#issuecomment-346787237

奇怪的是,实际上/etc/pam.d/su包括包含/etc/pam.d/common-session的调用,pam_systemd但这失败了,实际上/var/log/auth.log说:

pam_systemd(su:session):无法创建会话:已在会话中运行

目前,一个好方法是使用以ssh另一个用户的身份连接到同一台机器,类似于ssh user@localhost

答案4

systemd 248(2021 年 3 月发布)引入了语法

systemctl --user -M username@ status

(该命令需要以 root 身份运行)

例如

[myuser@laptop ~]$ sudo systemctl --user -M testuser@ status
● testuser@
    State: running
     Jobs: 0 queued
   Failed: 0 units
    Since: Thu 2022-11-03 22:59:10 CET; 164ms ago
   CGroup: /user.slice/user-1492.slice/[email protected]
           ├─init.scope
           │ ├─ 21922 /usr/lib/systemd/systemd --user
           │ └─ 21929 "(sd-pam)"
           └─session.slice
             └─dbus-broker.service
               ├─ 21950 /usr/bin/dbus-broker-launch --scope user
               └─ 21951 dbus-broker --log 4 --controller 9 --machine-id fa369ab69fcf4e54ad8a274517ea5096 --max-bytes 100000000000000 --max-fds 25000000000000 --max-matches 5000000000

或者您也可以打开一个新的交互式登录会话

[myuser@laptop ~]$ sudo machinectl shell testuser@
Connected to the local host. Press ^] three times within 1s to exit session.
[testuser@laptop ~]$ systemctl --user status
● laptop
    State: running
     Jobs: 0 queued
   Failed: 0 units
    Since: Thu 2022-11-03 22:56:50 CET; 57s ago
   CGroup: /user.slice/user-1492.slice/[email protected]
           └─init.scope
             ├─ 21799 /usr/lib/systemd/systemd --user
             └─ 21806 "(sd-pam)"

“sudo -u 用户名 -i”不会创建 systemd 登录会话

是 ”不是用于打开全新登录会话的工具“ 根据https://github.com/systemd/systemd/issues/7451#issuecomment-346787237 (我认为 sudo 与 su 相关。仅运行 sudo 成为另一个用户将不会启动该用户的 systemd 守护程序)

我尝试了一些例子Fedora 36systemd 250

例如“sudo -u 用户名 -i”

[myuser@laptop ~]$ sudo useradd test1
[myuser@laptop ~]$ sudo -u test1 -i
[test1@laptop ~]$ pgrep -u $USER -l
25217 bash
[test1@laptop ~]$ env | grep XDG
XDG_DATA_DIRS=/home/test1/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
[test1@laptop ~]$ 

例如“sudo machinectl shell 用户名@”

[myuser@laptop ~]$ sudo useradd test2
[myuser@laptop ~]$ sudo machinectl shell test2@
Connected to the local host. Press ^] three times within 1s to exit session.
[test2@laptop ~]$ pgrep -u $USER -l
25086 bash
25091 systemd
25100 (sd-pam)
25115 (sd-pam)
[test2@laptop ~]$ env | grep XDG
XDG_SESSION_TYPE=tty
XDG_SESSION_CLASS=user
XDG_SESSION_ID=51
XDG_RUNTIME_DIR=/run/user/1494
XDG_DATA_DIRS=/home/test2/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share/:/usr/share/
[test2@laptop ~]$ ls -l $XDG_RUNTIME_DIR/bus
srw-rw-rw-. 1 test2 test2 0 Nov  4 08:42 /run/user/1494/bus
[test2@laptop ~]$ 

参考:

相关内容来自systemd248 发行说明: https://github.com/systemd/systemd/blob/6c83054c0133eb53245e479d71589dceff76cf74/NEWS#L2796-L2800

相关内容