问题背景
在尝试通过Ansible自动化Podman和Plex容器部署时,遇到一个常见问题:当以新创建的非SSH用户身份运行systemctl --user
命令时,会出现错误:
1
Failed to connect to bus: No medium found
问题原因
这个问题通常是由于用户会话未正确初始化导致的。当用户通过su
、sudo
等方式切换,而不是通过SSH直接登录时,用户的systemd实例不会自动启动。
解决方案
1. 使用machinectl shell
代替su
1
sudo machinectl shell --uid=<username>@
这种方法比设置SSH登录更简洁,特别是对于那些不应该有SSH访问权限的用户。
2. 在Ansible中自动化解决方案
对于使用Ansible自动化的情况,可以通过以下方式解决:
1
2
3
4
5
6
- name: Enable Container at runtime -
become_user: ''
ansible.builtin.systemd:
name: 'container-.service'
enabled: true
scope: user
关键点是设置scope: user
参数。
3. 设置XDG_RUNTIME_DIR环境变量
1
2
3
mkdir -p ~/.bashrc.d
echo "export XDG_RUNTIME_DIR=/run/user/$(id -u)" > ~/.bashrc.d/systemd
source ~/.bashrc.d/systemd
或者直接在命令行中设置:
1
runuser -l <user> -c 'export XDG_RUNTIME_DIR=/run/user/$UID && systemctl --user status <service name> --no-pager'
4. 使用systemd 248+的新功能
对于systemd 248及以上版本(2021年3月发布),可以直接使用:
1
sudo systemctl --user -M username@ status myunit.service
例如:
1
sudo systemctl --user -M gitlab-runner@ --now enable podman.socket
最佳实践
- 避免使用su/sudo切换用户:始终通过SSH直接登录用户,或者使用
machinectl shell
命令 - 删除并重建受影响用户:如果用户会话已经损坏,最简单的解决方案是删除并重建用户
- 在Ansible中正确配置:使用
scope: user
参数和become_user
指令
总结
这个问题本质上是由于用户会话管理方式不当导致的。通过正确的工具和方法(如machinectl
、Ansible的适当配置或环境变量设置),可以有效地解决这个问题,实现自动化部署和管理用户级systemd服务。
对于使用Podman或其他容器技术的场景,确保用户会话正确初始化是保证容器服务能够作为用户级服务正常运行的关键。
本文由作者按照
CC BY 4.0
进行授权