Quando GNU greptenta 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 ifdichiarazione prende sempre il elseramo.
Per illustrare questo (questo non è esattamente ciò che sta accadendo nel tuo caso, ma mostra cosa succede se GNU grepnon è in grado di scrivere il suo output):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Qui siamo grepper la stringa che echoproduce, ma chiudiamo entrambi i flussi di output in grepmodo 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, grepsui 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 grepcon la sua -qopzione poiché non siamo affatto interessati a vedere l'output da esso (questo generalmente accelererebbe anche grepperché 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 pingdirettamente, 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 breakcon eg sleep 10mo qualcosa del genere se si prevede che il server alla fine ritorni.
Ho anche leggermente modificato le opzioni utilizzate con pingpoiché -i 1non 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;...