在sudo su - myuser后,我能否使用'systemctl --user'来控制用户systemd?

29
我想在系统启动时启动一个服务。我已经创建了一个名为ap@.service的模板定义,因为可能会有多个实例。
在根systemd中定义,这很好地运行,可以随系统启动和停止服务。使用systemctl enable ap@inst1 安装服务实例。Root用户也能够顺利启动和停止服务。该服务在自己的帐户(myuser)中运行,而不是root,由ap@.service模板中的User=myuser控制。
但是,我希望用户“myuser”能够启动和停止他们自己的服务,而不会影响系统安全性。
我切换到使用了user systemd,并使用loginctl enable-linger myuser使其保持登录状态。我然后启用了~myuser/.config/systemd/user目录中定义的服务。现在,服务按预期与系统干净地启动和停止。如果我作为“myuser”登录终端,那么systemctl --user start ap@inst1systemctl --user stop ap@inst1都能完美地工作。
但是,如果我作为另一个用户(user2)登录并在终端中执行sudo su - myuser,那么systemctl --user命令将失败,并显示错误消息“Failed to get D-Bus connection: no such file or directory”。
如何使sudo su - myuser命令切换用户后,systemctl --user 命令正常工作?

你的CWD仍然是另一个用户的主目录吗?如果调用用户没有权限查看当前目录,一些实用程序可能会出现问题。 - Dave
嗨,戴夫...主目录已经切换,是由于sudo命令中的“-”所强制执行的。当前工作目录已更改为新用户的主目录。 - NeilCasey
啊好的,那就忽略我吧。 - Dave
2个回答

34

在使用不同的关键词进行进一步搜索后,我在另一个网站上找到了答案。

所需的解决方案是为shell提供信息以达到用户正确的DBus。

在运行systemctl --user之前,在shell中添加以下环境变量,可以消除DBus问题,并使systemctl正常运行。

export XDG_RUNTIME_DIR="/run/user/$UID"
export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
为确保在sudo shell中可用DBUS_SESSION_BUS_ADDRESS,我将环境变量添加到目标用户ID的~/.bash_profile中。这需要创建登录shell(sudo su - myusersudo -l myuser)以创建正确的环境。
或者,将环境变量的创建添加到~/.bashrc(或其他shell的等效文件)。这将为所有shell创建重新建立环境。

那可能有效,但肯定有更好的方法来实现它。也许可以在su和PAM配置文件中找到。 - Bachsau
1
只有在事先启用了lingering(如OP所述),这才对我有效。如果禁用lingering,则/run/user/$UID目录不存在,无论如何都会导致systemctl --user命令失败。 对我来说,设置XDG_RUNTIME_DIR环境变量就足够了。 - morrow

3

systemd 248(2021年3月发布)引入了支持语法-M myuser@来指定另一个用户。

$ sudo systemctl --user -M myuser@ start ap@inst1

一点提示: 如果您想为用户myuser获取交互式登录shell

$ sudo machinectl shell myuser@

1
当我运行第一个命令时,我会得到“无法远程访问用户实例”的错误。 - Adam Głowacki
1
可能是systemd版本太旧了?这个功能是在systemd 248中引入的(参见https://github.com/systemd/systemd/blob/28795f2c138203fb700fc394f0937708af886116/NEWS#LL2820C10-L2820C10) - Erik Sjölund
Erik,你是对的。我使用的是239版本(RHEL8)。 - Adam Głowacki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接