Lorsque GNU grepessaie d'écrire son résultat, il échouera avec un état de sortie différent de zéro, car il n'a nulle part où écrire la sortie, car la connexion SSH a disparu.
Cela signifie que l' ifinstruction prend toujours la elsebranche.
Pour illustrer cela (ce n'est pas exactement ce qui se passe dans votre cas, mais cela montre ce qui se passe si GNU grepn'est pas en mesure d'écrire sa sortie):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Ici, nous greppour la chaîne qui echoproduit, mais nous fermons les deux flux de sortie pour grepqu'il ne puisse écrire nulle part. Comme vous pouvez le voir, l'état de sortie de GNU grepest 2 plutôt que 0.
Ceci est particulier à GNU grep, grepsur les systèmes BSD ne se comportera pas de la même manière:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
Pour y remédier, assurez-vous que le script ne génère pas de sortie. Vous pouvez le faire avec exec >/dev/null 2>&1. De plus, nous devrions utiliser grepavec son -qoption car nous ne sommes pas du tout intéressés à voir la sortie de celui-ci (cela accélérerait également généralement le grepcar il n'a pas besoin d'analyser tout le fichier, mais dans ce cas, cela fait très peu différence de vitesse car le fichier est si petit).
En bref:
#!/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
Vous pouvez également utiliser un test pingdirectement, supprimant le besoin d'un des fichiers intermédiaires (et supprimant également l'autre fichier intermédiaire qui ne contient vraiment qu'un horodatage):
#!/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
Dans les deux variantes du script ci-dessus, j'ai choisi de quitter la boucle en cas d'échec pour atteindre l'hôte, juste pour minimiser le nombre d'e-mails envoyés. Vous pouvez à la place remplacer le breakpar exemple sleep 10mou quelque chose si vous vous attendez à ce que le serveur réapparaisse finalement.
J'ai également légèrement modifié les options utilisées avec pingcar cela -i 1n'a pas beaucoup de sens -c 1.
Plus court (sauf si vous souhaitez qu'il continue à envoyer des e-mails lorsque l'hôte est inaccessible):
#!/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
En tant que tâche cron exécutée toutes les minutes (continuerait d'envoyer des e-mails toutes les minutes si le serveur continuait à être en panne):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
:? Ça aurait du sens pour moi s'il s'agissait d'un point-virgule;...