cron 脚本不会像它应该的那样重新启动

cron script won't reboot as it should

我有一个 Raspberry Pi 通过 openvpn 连接到 VPN。定期,连接断开,所以我使用以下脚本:

#!/bin/bash
ps -ef | grep -v grep | grep openvpn
if [ $? -eq 1 ] ; then
        /sbin/shutdown -r now
fi

我把它添加到crontab(使用sudo crontab -e),我希望脚本每5分钟执行一次:

*/5 * * * * /etc/openvpn/check.sh

脚本不起作用,但似乎仍然每五分钟执行一次:

tail /var/log/syslog | grep CRON

给出:

Mar 16 21:15:01 raspberrypi CRON[11113]: (root) CMD (/etc/openvpn/check.sh)
...

此外,当我使用 sudo ./check.sh 手动 运行 脚本时,Pi 会正常重启。

我不太明白这是怎么回事?

编辑 :

按照建议,我添加了完整路径名并从重启 Pi 到重启 openvpn:

#!/bin/bash
if ! /bin/ps -ef | /bin/grep '[o]penvpn'; then
        cd /etc/openvpn/
        /usr/sbin/openvpn --config /etc/openvpn/config.ovpn
fi

尽管我自己执行它运行没问题,但该脚本仍然无法运行。脚本的权限是755,应该没问题吧?

脚本的路径名与最后的grep匹配,所以找到了自己,满意了。

这没有以交互方式发生的原因是您没有运行它的完整路径。

这是一个非常常见的常见问题解答(扭曲)。

切线地,您的脚本包含两个非常常见的反模式。您正在重新发明 pidof 很糟糕,并且您正在明确检查 $?。除非你特别要求退出代码为 1,否则你应该简单地做

if ! ps -ef | grep -q '[o]penvpn'; then

因为 if 目的 是 运行 命令并检查其退出代码;还要注意使用与自身不匹配的正则表达式的技巧。但是使用 pidof 还可以让您轻松地只检查二进制可执行文件的文件名,而不是它的路径。

我终于明白为什么脚本不起作用了。由于它位于 /etc/openvpn 下,条件 if ! ps -ef | grep -q '[o]penvpn' 不会 return true 因为正在执行脚本。当我将 crontab 行更改为:

时,我注意到了这一点
*/5 * * * * /etc/openvpn/check.sh >/home/pi/output 2>/home/pi/erroutput

output 文件显示 /etc/openvpn/check.sh 脚本是 运行。


现在的脚本是:

#!/bin/bash
if ! pidof openvpn; then
        cd /etc/openvpn/
        /usr/sbin/openvpn --config /etc/openvpn/config.ovpn
fi

这很好用。谢谢大家