文章

问题背景

在尝试通过Ansible自动化Podman和Plex容器部署时,遇到一个常见问题:当以新创建的非SSH用户身份运行systemctl --user命令时,会出现错误:

1
Failed to connect to bus: No medium found

问题原因

这个问题通常是由于用户会话未正确初始化导致的。当用户通过susudo等方式切换,而不是通过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

最佳实践

  1. 避免使用su/sudo切换用户:始终通过SSH直接登录用户,或者使用machinectl shell命令
  2. 删除并重建受影响用户:如果用户会话已经损坏,最简单的解决方案是删除并重建用户
  3. 在Ansible中正确配置:使用scope: user参数和become_user指令

总结

这个问题本质上是由于用户会话管理方式不当导致的。通过正确的工具和方法(如machinectl、Ansible的适当配置或环境变量设置),可以有效地解决这个问题,实现自动化部署和管理用户级systemd服务。

对于使用Podman或其他容器技术的场景,确保用户会话正确初始化是保证容器服务能够作为用户级服务正常运行的关键。

本文由作者按照 CC BY 4.0 进行授权