crontab 中的脚本仅部分执行

crontab 中的脚本仅部分执行

我的情况:

我在 Raspberry Pi 上有一些 Python 脚本。它们的行为就像服务一样,它们会永远运行而不会退出并处理信号。它们应该在后台运行,将一些值写入 MariaDB。它们无人值守运行,无需登录用户。

但是,有时它们会崩溃。我不知道为什么,而且在我看来,很难找出发生了什么(随机崩溃,没有模式,没有线索,有时它们运行数月,有时它们每天都崩溃)。

由于该脚本处理的信号并不重要,我只想:

  1. 编写一个 shell 脚本,终止所有正在运行的 python 脚本并重新启动它们
  2. 使用 crontab 每天运行两次此脚本,这样如果出现崩溃,我不会丢失太多数据,也不必关心检查和重新启动它们

我已经编写了 shell 脚本“restart.sh”,并且在 bash 中执行它效果很好:

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
kill $(pgrep python3)
sleep 2
nohup python3 script1.py &
sleep 2
nohup python3 script2.py &
sleep 2
nohup python3 script3.py &
sleep 2
exit

我还修改了我的 crontab sudo crontab -e,其中包含以下内容:

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 9 * * * /home/pi/restart.sh
0 15 * * * /home/pi/restart.sh

我的问题:

测试 crontab,我可以看到restart.sh执行了,但只有第一个命令(kill命令)有效。所有正在运行的 python3 脚本都被终止,但没有重新启动。

我尝试添加PATHSHELL,因为这似乎是常见问题,但这并没有改变任何事情。

我也尝试过首先进行编辑,crontab -e但没有sudo,问题是一样的。

我在这里遗漏了什么?为什么如果我在终端中手动nohup运行命令,它们就不会像以前那样执行?我该怎么做才能使用 crontab 启动这些脚本?./restart.sh

答案1

使用 pkill 而不是 pgrep 可能更干净,但我不认为这是问题所在。

从您提供的信息来看,我不确定为什么您的脚本不能按预期工作(在我看来它没问题)。

但是我不确定在从 cron 命令调用的脚本中使用“&”是否正确。我的第一个替代建议是利用 cron 本身在后台运行的事实,并为每个 python 脚本设置一个单独的 cron 作业,而不是一次性完成所有任务。

如果我理解正确的话,症状是 python 程序完全崩溃而不是挂起,并且假设如果它们正常运行,最好让它们继续运行,您可以使用启动(如果不运行)脚本(我使用 bash):

#!/bin/bash
value=$( ps -ef | grep -ic "$1" )
if [ $value -lt 2 ]
then
    python3 "$1"
fi

然后在你的 crontab 中:

15 * * * * bash /path/to/script/start-if-not-running.bash script1.py
30 * * * * bash /path/to/script/start-if-not-running.bash script2.py
45 * * * * bash /path/to/script/start-if-not-running.bash script3.py

解释:

ps -ef搜索进程表的整个命令行(pgrep 和 pkill 默认只搜索前 13 个字符)

$value -lt 2意思是如果匹配的次数少于两次,那么继续并启动一个新脚本(总会有一个匹配项 - 即 grep 命令本身)

如果你还没有设置,我强烈建议你确保你的树莓派能通过电子邮件向你发送 cron 命令的输出(例如https://medium.com/swlh/setting-up-gmail-and-other-email-on-a-raspberry-pi-6f7e3ad3d0e) 作为调试的辅助。

相关内容