Próbuję tutaj napisać skrypt powłoki, który ciągle testuje mój serwer i wysyłać mi e-maile, gdy przestanie działać.
Problem polega na tym, że kiedy wylogowuję się z połączenia ssh, pomimo uruchomienia go &
na końcu polecenia, na przykład ./stest01.sh &
, automatycznie wpada w inne i nieprzerwanie wysyła mi pocztę, dopóki nie zaloguję się ponownie i nie zabiję go.
#!/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!" myemail@address.com < sdown.txt ;
sleep 10 ;
fi
done
linux
shell-script
grep
ping
Vasconcelos1914
źródło
źródło
:
? Dla mnie miałoby to sens, że to był średnik;
...:
robi nic. Właśnie po to jest przeznaczony. Tutaj zamiast odwracać test, używają go do wcześniejszego braku operacjielse
.Odpowiedzi:
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 przyjmujeelse
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):Tutaj mamy
grep
dla ciągu, któryecho
produkuje, ale zamykamy oba strumienie wyjściowe dlagrep
, aby nie mógł nigdzie pisać. Jak widać, status wyjścia GNUgrep
to 2 zamiast 0.Dotyczy to zwłaszcza GNU
grep
,grep
w systemach BSD nie będą zachowywać się tak samo: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łobygrep
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:
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):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):
Jako zadanie crona uruchamiane co minutę (kontynuowałoby wysyłanie wiadomości e-mail co minutę, jeśli serwer nadal nie działa):
źródło
>&-
spowoduje zamknięcie fd (jak w, deskryptor pliku 1 jest zamknięty), podczas gdy zamknięcie połączenia SSH będzie miało inny efekt (deskryptor pliku będzie nadal dostępny, ale nie będzie podłączony do niczego po drugiej stronie.) Myślę, że o to chodzi nadal stoi, to znaczy, że GNU grep kończy niezerowe, jeśli spróbuje zapisać dane wyjściowe, a to się nie powiedzie. Tak, najlepszym rozwiązaniem jest po prostu sprawdzenie statusu wyjścia ping bezpośrednio.exec </dev/null >/dev/null 2>&1
blisko początku. W ten sposób, jeśli np.ping
Zdecyduje się napisać coś do stderr, nie spowoduje to problemu./dev/null
stąd standardowe wejście , ale uporządkowałem wynik. Dzieki za sugestie.