web-dev-qa-db-ja.com

リモートからサーバーをテストし続けるシェルスクリプトを書き込もうとしたが、ログアウトするとelseステートメントに落ち続ける

ここで、サーバーをテストし続け、サーバーがダウンしたときにメールで通知するシェルスクリプトを記述しようとしています。

問題は、ssh接続からログアウトすると、&のように、コマンドの最後に./stest01.sh &を付けて実行しても、自動的に別の場所に分類され、再度ログインして強制終了するまで中断なしにメールを送信し続けることです。それ。

#!/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!" [email protected] < sdown.txt ;
        sleep 10 ;
    fi
done
9
Vasconcelos1914

GNU grepが結果を書き込もうとすると、SSH接続が失われたため、出力を書き込む場所がないため、ゼロ以外の終了ステータスで失敗します。

つまり、ifステートメントは常にelseブランチを使用します。

これを説明するために(これは正確に)ではありませんあなたのケースで何が起こっているか、しかしGNU grepが出力を書き込めない場合に何が起こるかを示しています) :

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

ここでは、grepが生成する文字列をechoしていますが、grepの両方の出力ストリームを閉じて、どこにも書き込めないようにしています。ご覧のとおり、GNU grepの終了ステータスは0ではなく2です。

これは特定のGNU= grepgrepはBSDシステムでは同じように動作しません。

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

これを修正するには、スクリプトが出力を生成しないことを確認してください。これはexec >/dev/null 2>&1で実行できます。また、grep-qオプションとともに使用する必要があります。これはseeingからの出力にはまったく関心がないためです(これにより、通常、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!" [email protected] <sdown.txt
        break
    fi

    sleep 10
done

pingのテストを直接使用して、中間ファイルの1つを不要にすることもできます(実際には、日付スタンプのみを含む他の中間ファイルも削除します)。

#!/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!" [email protected]
        break
    fi

    sleep 10
done

上記のスクリプトの両方のバリエーションでは、送信される電子メールの数を最小限に抑えるために、ホストに到達できなかった場合にループを終了することを選択しています。代わりに、breakを次のように置き換えることができます。 sleep 10mまたはサーバーが最終的に再起動すると予想される場合は何か。

-i 1-c 1ではあまり意味がないので、pingで使用するオプションも少し調整しました。

より短い(ホストに到達できないときにメールを送信し続けたい場合を除く):

#!/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!" [email protected]

毎分実行するcronジョブとして(サーバーがダウンし続けると、毎分メールを送信し続けるでしょう):

* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" [email protected] )
20
Kusalananda