![systemd 服务:权限被拒绝](https://linux22.com/image/1582257/systemd%20%E6%9C%8D%E5%8A%A1%EF%BC%9A%E6%9D%83%E9%99%90%E8%A2%AB%E6%8B%92%E7%BB%9D.png)
我有一个新的 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>
只是它!