Kiedy GNU grep
próbuje zapisać swój wynik, zakończy się niepowodzeniem z niezerowym statusem wyjścia, ponieważ nie ma gdzie zapisać danych wyjściowych, ponieważ połączenie SSH zniknęło.
Oznacza to, że if
instrukcja zawsze przyjmuje else
gałąź.
Aby to zilustrować (nie jest tak dokładnie w twoim przypadku, ale pokazuje, co się stanie, jeśli GNU grep
nie będzie w stanie zapisać swoich danych wyjściowych):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Tutaj mamy grep
dla ciągu, który echo
produkuje, ale zamykamy oba strumienie wyjściowe dla grep
, aby nie mógł nigdzie pisać. Jak widać, status wyjścia GNU grep
to 2 zamiast 0.
Dotyczy to zwłaszcza GNU grep
, grep
w systemach BSD nie będą zachowywać się tak samo:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
Aby temu zaradzić, upewnij się, że skrypt nie generuje danych wyjściowych. Możesz to zrobić za pomocą exec >/dev/null 2>&1
. Powinniśmy także korzystać grep
z tej -q
opcji, ponieważ wcale nie jesteśmy zainteresowani wyświetlaniem danych wyjściowych (generalnie przyspieszyłoby grep
to, ponieważ nie trzeba analizować całego pliku, ale w tym przypadku robi to niewiele różnica prędkości, ponieważ plik jest tak mały).
W skrócie:
#!/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
Możesz również użyć testu ping
bezpośrednio, usuwając potrzebę jednego z plików pośrednich (a także pozbywając się drugiego pliku pośredniego, który tak naprawdę tylko zawiera znacznik danych):
#!/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
W obu wariantach powyższego skryptu wybieram wyjście z pętli po nieosiągnięciu hosta, aby zminimalizować liczbę wysłanych wiadomości e-mail. Możesz zamiast tego zamienić na break
np. sleep 10m
Lub coś, jeśli spodziewasz się, że serwer w końcu się pojawi.
Lekko poprawiłem również używane opcje, ping
ponieważ -i 1
nie ma to większego sensu -c 1
.
Krótszy (chyba że chcesz, aby nadal wysyłał e-maile, gdy host jest nieosiągalny):
#!/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
Jako zadanie crona uruchamiane co minutę (kontynuowałoby wysyłanie wiadomości e-mail co minutę, jeśli serwer nadal nie działa):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
:
? Dla mnie miałoby to sens, że to był średnik;
...