从 systemd 服务调用 pactl 总是报告“pa_context_connect() 连接失败被拒绝”

问题描述 投票:0回答:2

我已经设置了一个 systemd 服务文件来在系统启动时执行一些 pactl 操作以进行测试过程。虽然从终端执行这些命令时工作正常,但通过启动服务从 systemd 服务运行相同的脚本时,我总是收到“pa_context_connect() 连接失败被拒绝”的消息。我还在服务文件中使用“User=”指令来确保自动登录用户与用于运行服务命令的用户匹配。

我读到这在某种程度上与pulseaudio会话在systemd服务的无环境上下文中无效有关,但我无法进一步弄清楚这一点。

pulseaudio systemd
2个回答
9
投票

尽管对于您可能正在从事的任何项目来说可能有点晚了,但这就是我发现的。

常规的systemctl,PID为1,在启动服务时确实无法访问当前用户的环境变量。由于 pactl 依赖这些变量来查找它需要连接到的pulseaudio 实例,因此当通过服务启动时它无法这样做。我确信有一个相当肮脏的解决方法,但我找到了更好的方法。

大多数系统都有第二个 systemd 实例在用户空间中运行(可以通过

systemctl --user
访问,但不以 root 身份连接)。该实例确实可以访问所有用户空间环境变量,并且我发现 pactl 在直接调用或通过脚本调用时不会返回任何错误。

您需要做的就是将服务放入

/usr/lib/systemd/user/
/etc/systemd/user/
~/.config/systemd/user/
,从服务文件中删除
User=
指令并以普通用户身份运行
systemctl --user daemon-reload
以确保它们已被发现了。


0
投票

在我看来,将守护进程移至用户服务是确保消除横向麻烦的最佳方法。

尽管如此,在我的用例中,我仍然不确定这是一个好方法。所以我寻找 PulseAudio 缺少的环境变量。

看来只需要一个,那就是

XDG_RUNTIME_DIR

然后,只需在

[Service]
部分添加此行:

Environment=XDG_RUNTIME_DIR=/run/user/1000

在我的例子中,1000 是我的服务用户的用户 ID。您可以通过在以服务用户身份登录的 shell 中输入命令

id
来获取您的服务。

如果这不是您可以连接的用户,只需检查第三列

/etc/passwd
中的号码。

以我为例,我有这样一行:

anc:x:1000:1000:,,,:/home/anc:/bin/bash

这是第一个

1000
,在
x
之后。

© www.soinside.com 2019 - 2024. All rights reserved.