我有个人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
系统上的环境:env
crontab
* * * * * /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
。您的问题并未表明您是否使用su
或sudo
,因此我仔细研究了这个问题,以明确两点:
- 如果你的
cron
工作需要root
特权,那么或许最好从 运行该作业。另一种root crontab
方法是使用 ,如果需要身份验证(通常情况下),这可能会很尴尬。sudo
user crontab
sudo
- 可以
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.sh
和auto_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
。