Lorsque GNU grep
essaie 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' if
instruction prend toujours la else
branche.
Pour illustrer cela (ce n'est pas exactement ce qui se passe dans votre cas, mais cela montre ce qui se passe si GNU grep
n'est pas en mesure d'écrire sa sortie):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Ici, nous grep
pour la chaîne qui echo
produit, mais nous fermons les deux flux de sortie pour grep
qu'il ne puisse écrire nulle part. Comme vous pouvez le voir, l'état de sortie de GNU grep
est 2 plutôt que 0.
Ceci est particulier à GNU grep
, grep
sur 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 grep
avec son -q
option 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 grep
car 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 ping
directement, 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 break
par exemple sleep 10m
ou 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 ping
car cela -i 1
n'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;
...