ここで、サーバーをテストし続け、サーバーがダウンしたときにメールで通知するシェルスクリプトを記述しようとしています。
問題は、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
GNU grep
が結果を書き込もうとすると、SSH接続が失われたため、出力を書き込む場所がないため、ゼロ以外の終了ステータスで失敗します。
つまり、if
ステートメントは常にelse
ブランチを使用します。
これを説明するために(これは正確に)ではありませんあなたのケースで何が起こっているか、しかしGNU grep
が出力を書き込めない場合に何が起こるかを示しています) :
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
ここでは、grep
が生成する文字列をecho
していますが、grep
の両方の出力ストリームを閉じて、どこにも書き込めないようにしています。ご覧のとおり、GNU grep
の終了ステータスは0ではなく2です。
これは特定のGNU= grep
、grep
は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] )