systemd 服务:权限被拒绝

systemd 服务:权限被拒绝

我有一个新的 systemd 服务无法启动,并出现“权限被拒绝”错误。我买了一台 Thinkpad L480。不幸的是,内核似乎无法检测到触摸板。这个问题已经解决这里可以通过以下方法解决

sudo sh -c 'echo -n "elantech" > /sys/bus/serio/devices/serio1/protocol'

由于我不想在每次启动时都执行此操作,因此我创建了一个 systemd 服务,但它无法按预期工作。

我的 touchpad_enabler.service 是

[Unit]
Description=FooBar

[Service]
Type=oneshot
ExecStart=/usr/local/bin/enable_touchpad.sh

[Install]
WantedBy=default.target

脚本文件很简单

#!/bin/bash

echo -n "elantech" > /sys/bus/serio/devices/serio1/protocol

但我也尝试了该sh -c版本。我通过以下方式调整了权限

sudo chmod 744 /usr/local/bin/enable_touchpad.sh
sudo chmod 644 /etc/systemd/system/touchpad_enabler.service

因此这两个文件都归 root 所有。然后我通过以下方式启用它

systemctl enable enable_touchpad.sh

当我通过 手动启动服务时systemctl start touchpad_enabler.service,它运行正常,触摸板也正常工作。然而,在启动时,服务失败,并在 中列为“失败” systemctl list-units

的输出journalctl -b -u touchpad_enabler.service是:

systemd[1]: Starting Solves bug that Thinkpad L480 Touchpad is not correctly detected...
enable_touchpad.sh[516]: sh: /sys/bus/serio/devices/serio1/protocol: permission denied
systemd[1]: touchpad_enabler.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: touchpad_enabler.service: Failed with result 'exit-code'.
systemd[1]: Failed to start FooBar

看起来问题出在文件本身的写入权限上。但手动启动服务没问题,而且据我了解,systemd 无论如何都应该以 root 身份执行该命令,对吗?

通过阅读,man systemctl.service我想到在文件路径前面加上“+”,这样就可以读取

ExecStart=+/usr/local/bin/enable_touchpad.sh

没有效果。

我不太明白这个protocol文件是从哪里来的。它看起来像是在启动时由内核创建的?所以我也试验了这个After=参数,但 systemd 应该在内核完全加载后启动服务,对吗?该文件也归 root 所有,所以我预计不会出现任何问题。

我希望有人能帮助我。提前致谢。

答案1

看起来您对服务和脚本文件有点困惑。不过文件的内容似乎应该可以正常工作。

Systemd 需要服务文件。请将此文件放在此处

/etc/systemd/system/touchpad_enabler.service

内容如下:

[Unit]
Description=FooBar

[Service]
Type=oneshot
ExecStart=/usr/local/bin/enable_touchpad.sh

[Install]
WantedBy=default.target

然后是您的脚本(我更改了名称以使服务文件和脚本文件之间的分离更清晰。也是/usr/local/bin一个更好的地方,因为它通常用于本地脚本/程序)

/usr/local/bin/enable_touchpad.sh

其内容如下(不变):

#!/bin/bash
echo -n "elantech" > /sys/bus/serio/devices/serio1/protocol

确保脚本和服务文件的权限正确。它们应该由 root 拥有,并且脚本应该是可执行的。

sudo chmod 744 /usr/local/bin/enable_touchpad.sh
sudo chmod 644 /etc/systemd/system/touchpad_enabler.service

然后启用 systemd 服务。

sudo systemctl enable touchpad_enabler.service

这将启用该服务,使其在启动时运行。也可以使用以下命令手动运行:

sudo systemctl start touchpad_enabler.service

或者您可以直接运行脚本,绕过 systemd 服务:

sudo /usr/local/bin/enable_touchpad.sh

我实际上无法说出该错误或协议文件何时创建,但该服务应该可以正常工作。

编辑:
您可以将After=参数添加到[Unit]服务部分,以确保它在特定目标(如default.target或 )之后运行multi-user.target。默认情况下,每个服务都依赖于sysinit.target,所以我不确定这对您来说有多重要。

如果你看这里,https://stackoverflow.com/questions/27511139/how-to-make-sysfs-changes-persistent-in-centos-7-systemd,还有其他方法可以实现您想要的功能,而无需自定义服务。也许您可以尝试 udev 规则。

答案2

我在我的 postgresql HA 服务‘Patroni’中遇到了同样的问题,因此我简单地注释掉用户和组行,如下所示:

[Service]
Type=simple

#User=postgres
#Group=postgres

ExecStart=/root/.local/bin/patroni /etc/patroni.yml

然后重新加载新配置:

systemctl daemon-reload;
systemctl start <service>

只是它!

相关内容