GNU grep
が結果を書き込もうとすると、SSH接続がなくなっているため、出力を書き込む場所がないため、ゼロ以外の終了ステータスで失敗します。
つまり、if
ステートメントは常にelse
分岐します。
これを説明するには(これはあなたのケースで正確に何が起こっているのかでgrep
はありませんが、GNU が出力を書き込めない場合に何が起こるかを示しています):
$ 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
オプション我々は内のすべての興味ではないですので、見て(これは、一般的にもスピードアップするでしょう、それからの出力を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
直接にテストを使用して、中間ファイルの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!" myemail@address.com
break
fi
sleep 10
done
上記のスクリプトの両方のバリエーションでは、送信された電子メールの数を最小限に抑えるために、ホストに到達できなかった場合にループを終了することを選択しています。サーバーが最終的に再起動することが予想される場合はbreak
、代わりに、たとえば、sleep 10m
または何かで置き換えることができます。
また、で使用するオプションを少し調整しping
ました-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 )
:
ませんが、コロンは何をしますか?それはセミコロンだったと私には理にかなってい;
ます...