在systemd下运行可执行文件时权限被拒绝
在我的Raspberry Pi 5(64位)上,我正尝试通过一个Python脚本来运行一个命令,并使用systemd在开机时启动它。流程是这样的:
ids.service in /etc/systemd/system/:
[Unit]
Description=IDs
After=multi-user.target
[Service]
ExecStart=/bin/sh /home/suntooth/ids/onreboot.sh
[Install]
WantedBy=multi-user.target
然后 onreboot.sh:
#! /usr/bin/bash
cd /home/suntooth/ids/
python ids.py
最后,ids.py 做了一些处理,并使用 subprocess.run(command, shell=True) 运行一个 yt-dlp 命令(yt-dlp -U [other irrelevant arguments])。which yt-dlp 返回 /user/suntooth/bin/yt-dlp,这是我在一个帮助帖子中发现的可执行文件的推荐位置,因为其他位置需要root权限才能访问。
在把我的Pi从自带的32位操作系统升级到64位(仍然是Raspberry Pi OS)之前,一切都运行得很完美,但现在它只抛出 sh[5943]: /bin/sh: 1: yt-dlp: Permission denied。它能正常到达Python脚本(在journalctl里有脚本的其他输出),但在某处失败。
我可以在终端运行 yt-dlp,如果我自己在终端运行 python ids.py,一切正常,但一旦由服务去执行,它就失败。
那么问题出在哪里?是什么导致systemd无法访问 yt-dlp 的权限?(请注意,我对终端,尤其是systemd并非经验丰富,如有可能,请用简洁易懂的方式解释。)
解决方案
[作者注释后的编辑]
你试过以你的用户身份运行吗?
你可以在你的服务文件中添加一行 User=。
[Service]
User=suntooth
ExecStart=/bin/sh /home/suntooth/ids/onreboot.sh
回答作者的评论:
你也可以尝试显式设置路径:
[Service]
User=suntooth
Environment=PATH=/home/suntooth/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/bin/sh /home/suntooth/ids/onreboot.sh
或者在Python中使用你的绝对路径:
# Instead of:
subprocess.run("yt-dlp -U ...", shell=True)
# Use the absolute path:
subprocess.run("/home/suntooth/bin/yt-dlp -U ...", shell=True)
以及最直观但仍然有效的建议:检查二进制文件的执行权限,如有必要,使用chmod +x修改。过去我经常遇到这种情况。
# Check permissions (you want -rwxr-xr-x, not -rw-r--r--)
ls -la /home/suntooth/bin/yt-dlp
# Re-add execute permission if missing
chmod +x /home/suntooth/bin/yt-dlp
如果都没法解决,我也会束手无策。