Linux

嘗試編寫一個持續遠端測試伺服器的 shell 腳本,但是當我註銷時它一直落在 else 語句中

  • October 9, 2019

在這裡嘗試編寫一個 shell 腳本來持續測試我的伺服器並在它出現故障時給我發電子郵件。

問題是,當我從 ssh 連接中註銷時,儘管&在命令結束時使用 like執行它,但./stest01.sh &它會自動落入 else 並不斷地向我發送郵件,直到我再次登錄並殺死它。

#!/bin/bash
while true; do
   date > sdown.txt ;
   cp /dev/null pingop.txt ;
   ping -i 1 -c 1 -W 1 myserver.net > pingop.txt &
   sleep 1 ;
   if
       grep "64 bytes" pingop.txt ;
   then
       :
   else
       mutt -s "Server Down!" myemail@address.com < sdown.txt ;
       sleep 10 ;
   fi
done

當 GNUgrep嘗試寫入其結果時,它將以非零退出狀態失敗,因為它無處可寫輸出,因為 SSH 連接已消失。

這意味著該if語句始終採用else分支。

為了說明這一點(這並不完全是您的情況,但它顯示瞭如果 GNUgrep無法寫入其輸出會發生什麼):

$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2

在這裡,我們grep為產生的字元串echo,但我們關閉了兩個輸出流,grep以便它不能在任何地方寫入。如您所見,GNU 的退出狀態grep是 2 而不是 0。

這是 GNU 特有的grepgrep在 BSD 系統上的行為不會相同:

$ echo 'hello' | grep hello >&- 2>&-    # using BSD grep here
$ echo $?
0

要解決此問題,請確保腳本不生成輸出。您可以使用exec >/dev/null 2>&1. 此外,我們應該使用grep它的-q選項,因為我們對查看它的輸出完全不感興趣(這通常也會加快速度,grep因為它不需要解析整個文件,但在這種情況下它幾乎沒有由於文件很小,因此速度差異)。

簡而言之:

#!/bin/sh

# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1

while true; do
   date >sdown.txt

   ping -c 1 -W 1 myserver.net >pingop.txt

   if ! grep -q "64 bytes" pingop.txt; then
       mutt -s "Server Down!" myemail@address.com <sdown.txt
       break
   fi

   sleep 10
done

您也可以ping直接使用測試,消除對其中一個中間文件的需要(並擺脫另一個實際上只包含日期戳的中間文件):

#!/bin/sh

exec >/dev/null 2>&1

while true; do
   if ! ping -q -c 1 -W 1 myserver.net; then
       date | mutt -s "Server Down!" myemail@address.com
       break
   fi

   sleep 10
done

在上述腳本的兩種變體中,我選擇在無法到達主機時退出循環,只是為了盡量減少發送的電子郵件數量。如果您希望伺服器最終再次出現,您可以將其替換為breakeg或其他內容。sleep 10m

我還稍微調整了與pingas一起使用的選項,-i 1-c 1.

更短(除非您希望它在主機無法訪問時繼續發送電子郵件):

#!/bin/sh

exec >/dev/null 2>&1

while ping -q -c 1 -W 1 myserver.net; do
   sleep 10
done

date | mutt -s "Server Down!" myemail@address.com

作為每分鐘執行的 cron 作業(如果伺服器繼續關閉,將繼續每分鐘發送電子郵件):

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )

引用自:https://unix.stackexchange.com/questions/535001