Kiedy GNU greppró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 ifinstrukcja zawsze przyjmuje elsegałąź.
Aby to zilustrować (nie jest tak dokładnie w twoim przypadku, ale pokazuje, co się stanie, jeśli GNU grepnie będzie w stanie zapisać swoich danych wyjściowych):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Tutaj mamy grepdla ciągu, który echoprodukuje, ale zamykamy oba strumienie wyjściowe dla grep, aby nie mógł nigdzie pisać. Jak widać, status wyjścia GNU grepto 2 zamiast 0.
Dotyczy to zwłaszcza GNU grep, grepw 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ć grepz tej -qopcji, ponieważ wcale nie jesteśmy zainteresowani wyświetlaniem danych wyjściowych (generalnie przyspieszyłoby grepto, 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 pingbezpoś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 breaknp. sleep 10mLub coś, jeśli spodziewasz się, że serwer w końcu się pojawi.
Lekko poprawiłem również używane opcje, pingponieważ -i 1nie 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;...