Networking

如何在網路故障時以 crontably 重啟 Linux 主機?

  • January 1, 2022

我有一個個人Ubuntu主機,連接到公共/共享 Wi-Fi AP(不受我控制)。

有時,它會出現網路問題,我很確定,僅重新啟動網路服務是行不通的。唯一的方法是重新啟動它。

我的計劃是添加一個 crontab 來測試網路連接。如果失敗,則重新啟動電腦。

如果我手動執行 auto_reboot.sh,它會在*ping*測試失敗時重新啟動。但是從 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. 你說:

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。您執行的任何腳本cron都無法找到不在 PATH 上的執行檔。

順便說一句,您cron只需env使用以下命令執行即可檢查系統上的環境crontab

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

在您的auto_reboot.sh,您未能為. 正如通常在 中找到的那樣,並且可能不在 使用的 PATH 中,這是一個潛在的問題。reboot``reboot``/sbin/reboot``/sbin cron

因此,我建議您驗證 使用的環境 (PATH) cron,並仔細檢查您的所有命令是:1) 在cronPATH 上,或 2) 使用完整路徑規範

2. 你把所有東西都跑出/root目錄

通常,/root不用於使用者腳本。也許你正在使用sudo?或者,也許你已經做了一個su成為根?如果是這種情況,我會評論說這不是最佳實踐,即使它仍然可以工作。我覺得最好的做法sudo從您的使用者帳戶中使用您需要的任何權限提升。

不想學究氣,我想說該root帳戶有一個crontab獨立於任何使用者 crontab執行的帳戶。此外,root crontab不需要sudo使用 - 在 中完成的所有操作root crontab都是通過root特權完成的。

綜上所述,我reboot在您的腳本中看到了對的呼叫 - 一個需要root 權限才能執行的命令。只有root crontab. _ 您的問題並未表明您是否正在使用suor sudo,因此我通過這個來努力澄清兩點:

  1. 如果您的cron作業需要root特權,最好root crontab. 另一種方法是sudouser crontab需要身份驗證的情況下使用可能會很尷尬sudo- 通常情況下。
  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) 中的程式碼合併到一個腳本中,因為這對我來說似乎更簡單,但你可能有充分的理由這樣做,而且沒有理由這樣做’如果操作正確,將無法正常工作。

引用自:https://serverfault.com/questions/1088713