修复systemd服务203/EXEC失败问题(找不到文件或目录)

90

我正在尝试设置一个简单的systemd定时器,每天午夜运行一个bash脚本。

systemctl --user status backup.service失败并记录以下内容:

backup.service: Failed at step EXEC spawning /home/user/.scripts/backup.sh: No such file or directory.

backup.service: Main process exited, code=exited, status=203/EXEC
Failed to start backup.
backup.service: Unit entered failed state.
backup.service: Failed with result 'exit-code'.

虽然文件和目录是存在的,脚本也是可执行的,我还把权限设置为了777,但我还是迷失了。

一些背景信息:

backup.timerbackup.service 单元文件位于 /home/user/.config/systemd/user

backup.timer 已加载并激活,目前正在等待午夜到来。

以下是它的样子:

[Unit]
Description=Runs backup at 0000

[Timer]
OnCalendar=daily
Unit=backup.service

[Install]
WantedBy=multi-user.target

这里是 backup.service

[Unit]
Description=backup

[Service]
Type=oneshot
ExecStart=/home/user/.scripts/backup.sh

[Install]
WantedBy=multi-user.target

最后,这是对backup.sh的释义:

#!/usr/env/bin bash

rsync -a --delete --quiet /home/user/directory/ /mnt/drive/directory-backup/

如果我自己执行脚本,它能够正常运行。
不确定是否相关,但我使用fish作为我的shell(从.bashrc启动)。
如果有帮助的话,我可以发布完整的脚本。

4
“ls -l /home/user/.scripts/backup.sh” 的输出是什么?你的 backup.sh 脚本开头看起来很奇怪:“#!/user/env/bin bash”,可执行文件“/user/env/bin”是否实际存在?你确定你没有想说“/usr/bin/env”或“/home/user/bin/env”吗? - nos
ls 输出 -rwxrwxrwx 1 dwrz dwrz 1470 Aug 11 01:57 /home/user/.scripts/backup.sh。抱歉,脚本中的 shebang 中的拼写错误是我复制到这里时发生的。实际上应该是 /usr/ - dwrz
附注:从.bashrc启动fish是一个非常糟糕的想法。更新您的/etc/passwd条目以直接指定fish,不要混淆可能有意要运行交互式bash实例的程序,使其启动一个不同的、不兼容的shell。 - Charles Duffy
至于眼前的紧急问题,我建议使用Sysdig跟踪执行来复现它;这样你就可以找到失败的确切系统调用,并提取相关细节(活动路径、用户ID、组ID等)。 - Charles Duffy
非常感谢,Charles。我没有在/etc/passwd中设置fish,因为Arch Wiki建议不要这样做,但是我很感激你的提醒,我也会研究一下。目前我尝试了两件事:(1)在服务文件中指定PATH,(2)在脚本中使用#!/bin/bash(当我自己执行它时仍然可以正常运行)。我仍然遇到了与systemd相同的错误(确保已经daemon-reload)。现在我要看一下sysdig - dwrz
显示剩余2条评论
8个回答

201

我想我找到了答案:

.service文件中,我需要在脚本路径前添加/bin/bash

例如,对于备份服​​务:

ExecStart=/bin/bash /home/user/.scripts/backup.sh

与之相反的是:

ExecStart=/home/user/.scripts/backup.sh

我不确定为什么。也许是因为fish。另一方面,我有一个用于邮件的脚本正在运行,服务文件似乎可以正常运行而不需要/bin/bash。但它使用default.target而不是multi-user.target

我看到大多数教程都没有加上/bin/bash,但我后来看到这个SO答案有它,并认为值得一试。

服务文件执行脚本,计时器列在systemctl --user list-timers中,希望这将起作用。

更新:我可以确认现在一切正常。


13
这对我很有帮助。它之所以能够在其他脚本中工作,是因为它们在开头有一个shebang(#!/bin/bash),而这个特定的脚本没有。 - Felix Müller
1
即使可执行文件不是一个bash脚本,例如在我的情况下,在CentOS 7上的jupyter中,/bin/bash -c "..."也是必需的。我认为这是因为它是一个Python脚本,并且在开头有一个python的shebang。 - WesternGun
1
有时候你需要执行 chmod +x /home/user/.scripts/backup.sh 命令。 - ST-DDT
1
在我的情况下,我缺少了.sh扩展名。 - nilesh
1
RHEL-9即使脚本从命令行执行正常,也需要"/bin/bash"。 - R.G.
显示剩余7条评论

19
为简化操作,请确保在ExecStart脚本顶部添加一个哈希标志,例如:

#!

#!/bin/bash

python -u alwayson.py    

10

今天我也遇到了一个Main process exited, code=exited, status=203/EXEC,我的问题是我忘记给文件添加可执行位。


1
我来到这里阅读了标记答案,并在阅读你的答案之前发现,只需执行chmod 700 <script>就解决了我的问题。这应该被标记为正确答案。我不需要像标记答案所说的那样添加/bin/bash <script-start>。 - nikolaosinlight

10

当我的脚本出现这个问题时,是因为它使用了 DOS 的换行符,这会导致位于脚本顶部的 shebang 行出现错误。我将其改为 Unix 的换行符后问题得到解决。


3
你救了我的命!我只是在.sh文件的第一行添加了#!/usr/bin/env bash,然后它就运行起来了。 - kujiy

8
如果这是你脚本中的复制/粘贴,那么你已经排列了这一行。
#!/usr/env/bin bash

这里没有 #!/usr/env/bin,你可能是想说 #!/usr/bin/env


1
很好,代码现在是正确的,但我可能之后修复了它。如果这是复制粘贴,那就可以解释了。 - dwrz

3

尝试运行:

systemctl daemon-reload

然后再次运行

service <yourservice> status

1

我遇到了类似的问题,改变了权限并添加了可执行权限

使用 chmod +x /etc/systemd/system/<service-filename>

这对我起作用了


0

我实际上使用了如何将node.js应用程序作为后台服务运行?的答案,结合上面dwrz所说的内容。在我的情况下,我正在创建一个需要在我不在场时能够运行的Discord机器人。

有了这个服务,我最初遇到了与初始帖子作者相同的错误,这也是我来到这里的原因。我忘记在执行的node.js脚本顶部添加#!/usr/bin/env node

从那以后就没有问题了,尽管我打算看看还可以将什么其他内容扩展到服务本身。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接