Quando GNU grep
tenta di scrivere il suo risultato, fallirà con uno stato di uscita diverso da zero, perché non ha un posto dove scrivere l'output, perché la connessione SSH è sparita.
Ciò significa che la if
dichiarazione prende sempre il else
ramo.
Per illustrare questo (questo non è esattamente ciò che sta accadendo nel tuo caso, ma mostra cosa succede se GNU grep
non è in grado di scrivere il suo output):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Qui siamo grep
per la stringa che echo
produce, ma chiudiamo entrambi i flussi di output in grep
modo che non possano scrivere da nessuna parte. Come puoi vedere, lo stato di uscita di GNU grep
è 2 anziché 0.
Questo è particolare per GNU grep
, grep
sui sistemi BSD non si comporterà lo stesso:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
Per ovviare a questo, assicurarsi che lo script non generi output. Puoi farlo con exec >/dev/null 2>&1
. Inoltre, dovremmo utilizzare grep
con la sua -q
opzione poiché non siamo affatto interessati a vedere l'output da esso (questo generalmente accelererebbe anche grep
perché non ha bisogno di analizzare l'intero file, ma in questo caso rende molto poco differenza di velocità poiché il file è così piccolo).
In breve:
#!/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
Puoi anche usare un test ping
direttamente, rimuovendo la necessità di uno dei file intermedi (e anche liberandoti dell'altro file intermedio che in realtà contiene sempre e solo un datestamp):
#!/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
In entrambe le varianti dello script sopra, scelgo di uscire dal loop in caso di mancato raggiungimento dell'host, solo per ridurre al minimo il numero di email inviate. Si potrebbe invece sostituire break
con eg sleep 10m
o qualcosa del genere se si prevede che il server alla fine ritorni.
Ho anche leggermente modificato le opzioni utilizzate con ping
poiché -i 1
non ha molto senso -c 1
.
Più breve (a meno che tu non voglia continuare a inviare e-mail quando l'host è irraggiungibile):
#!/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
Come cron job in esecuzione ogni minuto (continuerebbe a inviare e-mail ogni minuto se il server continua a non essere attivo):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
:
? Per me avrebbe senso che fosse un punto e virgola;
...