当网络出现故障时,如何定期重新启动 Linux 主机?

当网络出现故障时,如何定期重新启动 Linux 主机?

我有个人Ubuntu主机,连接到公共/共享 Wi-Fi美联社(不在我的控制范围内)。

有时候网络会出问题,我确定重启网络服务是不行的,唯一的办法就是重启。

我的计划是添加一个 crontab,以测试网络连接。如果失败,则重新启动计算机。

如果我手动运行 auto_reboot.sh,它会重新启动,当测试失败。但从 crontab 运行,它不起作用:)

这是我的 crontab 条目

crontab -l
* * * * * /root/loadrc/transmissionrc/auto_reboot.sh

文件/root/loadrc/transmissionrc/auto_reboot.sh

#!/bin/zsh

/root/loadrc/networkrc/ping.sh
rc=$?

if [[ $rc -eq 0 ]]
then
    echo "say The internet is back up."
else
    reboot
fi

文件/root/loadrc/networkrc/ping.sh

#!/bin/zsh
((count = 10))                           # Maximum number to try.

while [[ $count -ne 0 ]] ; do
    ping -c 1 8.8.8.8                    # Try once.
    rc=$?
    if [[ $rc -eq 0 ]] ; then
        ((count = 1))                    # If okay, flag loop exit.
    else
        sleep 1                          # Minimise network storm.
    fi
    ((count = count - 1))                # So we don't go forever.
done

exit $rc

我添加了一些日志,并故意关闭了 Wi-Fi 接口:

watch ifconfig wlan0 down
transmissionrc/auto_reboot.sh
#!/bin/zsh

echo "" > /root/loadrc/crontab.log

/root/loadrc/networkrc/ping.sh
rc=$?

if [[ $rc -eq 0 ]]
then
    echo "say The internet is back up."
else
    reboot
fi
networkrc/ping.sh
#!/bin/zsh
((count = 10))                           # Maximum number to try.


while [[ $count -ne 0 ]] ; do
    /usr/bin/ping -c 1 8.8.8.8 >> /root/loadrc/crontab.log 2>&1
    echo "step --> 2" >> /root/loadrc/crontab.log
    rc=$?

    if [[ $rc -eq 0 ]] ; then
        echo "step --> 3" >> /root/loadrc/crontab.log
        ((count = 1))                    # If okay, flag loop exit.
    else
        echo "step --> 4" >> /root/loadrc/crontab.log
        sleep 1                          # Minimise network storm.
    fi
    ((count = count - 1))                # So we don't go forever.
done

exit $rc

文件/root/loadrc/crontab.log

/usr/bin/ping: connect: Network is unreachable
step --> 2
step --> 3

这意味着,在crontab模式下,即使ping测试失败,返回代码仍然为零。

那么问题来了,如何在crontab模式下测试网络连接?

答案1

对于您的问题的可能解决方案,我有三个想法:

1. 您说:

If I manually run the auto_reboot.sh, it does reboot, when a ping test fail. But running from crontab, it is not working:)

通常,当命令在交互式 shell(从 CLI)中正常运行,但在cron它下面无法正常运行时,这是由于环境;例如,cron有一个与交互式 shell 不同的 PATH。通常cron环境为:PATH=/usr/bin:/bin任何脚本您运行的 run undercron将无法找到不在 PATH 上的可执行文件。

顺便说一下,您可以通过简单地运行以下命令来检查cron系统上的环境:envcrontab

* * * * * /usr/bin/env > /my/cronlog/location/mycronenvironment.txt 2>&1

在您auto_reboot.sh完整路径规范reboot。如reboot通常在/sbin/reboot和中发现的那样/sbin 未必在 使用的 PATH 中cron,这是一个潜在的问题。

最后,我建议您验证所使用的环境(PATH)cron,并仔细检查所有命令是否:1)在 PATH 上cron,或 2)使用完整路径规范

2. 运行/root目录中的所有内容

通常/root不用于用户脚本。也许您正在使用sudo?或者,也许您已经执行了su成为 root 的命令?如果是这种情况,我会评论这不是最佳实践,尽管它仍然可以工作。我觉得最佳实践是使用sudo你的用户考虑您需要的任何权限升级。

我不想吹毛求疵,但我想说的是,该root帐户有一个crontab独立于任何用户 crontab。此外,root crontab不需要sudo使用 - 在中完成的所有事情root crontab都是使用特权完成的root

综上所述,我看到了reboot脚本中的调用 - 该命令需要需要 root 权限才能运行。这将按照您编写的方式运行仅有的在 中使用时root crontab。您的问题并未表明您是否使用susudo,因此我仔细研究了这个问题,以明确两点:

  1. 如果你的cron工作需要root特权,那么或许最好从 运行该作业。另一种root crontab方法是使用 ,如果需要身份验证(通常情况下),这可能会很尴尬。sudouser crontabsudo
  1. 可以root crontab通过使用 从一个常规用户帐户访问sudo crontab -e;即无需su即可root访问root crontab

3. 你的脚本可能存在逻辑错误

正如指出的那样另一个答案,目前还不清楚您是否可以依赖脚本rc中的的值ping.sh作为 的条件reboot。不幸的是,这是否是一个问题被ping.sh您问题中似乎有两个不同版本的脚本所掩盖——目前还不清楚您是否在使用第一个版本:

#!/bin/zsh
((count = 10))                           # Maximum number to try.

while [[ $count -ne 0 ]] ; do
    ping -c 1 8.8.8.8                    # Try once.
    rc=$?

或第二个版本:

#!/bin/zsh
((count = 10))                           # Maximum number to try.


while [[ $count -ne 0 ]] ; do
    /usr/bin/ping -c 1 8.8.8.8 >> /root/loadrc/crontab.log 2>&1
    echo "step --> 2" >> /root/loadrc/crontab.log
    rc=$?

严格按照我的个人选择,我倾向于将这两个脚本(ping.shauto_reboot.sh)的代码合并为一个脚本,因为对我来说这似乎更直接,但您可能有充分的理由这样做,并且如果做得正确,它没有理由不起作用。

答案2

/usr/bin/ping -c 1 8.8.8.8 >> /root/loadrc/crontab.log 2>&1 
echo "step --> 2" >> /root/loadrc/crontab.log  
rc=$?

我认为这会检查命令的退出代码,echo而您的逻辑需要命令的退出代码ping

相关内容