Коли GNU grepнамагається записати свій результат, він вийде з ладу зі статусом ненульового виходу, тому що йому нікуди записати вихід, тому що з'єднання SSH відсутнє.
Це означає, що ifтвердження завжди бере elseгілку.
Щоб проілюструвати це (це не зовсім те, що відбувається у вашому випадку, але це показує, що станеться, якщо GNU grepне в змозі написати свій вихід):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Ось ми grepдля рядка, який echoвиробляє, але ми закриваємо обидва вихідні потоки для grepтого, щоб він нікуди не міг записати. Як бачимо, статус виходу GNU grepстановить 2, а не 0.
Це особливо стосується GNU grep, grepоскільки системи BSD не будуть вести себе так:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
Щоб виправити це, переконайтеся, що скрипт не генерує вихід. Ви можете це зробити за допомогою exec >/dev/null 2>&1. Крім того, ми повинні використовувати grepйого -qваріант, оскільки ми зовсім не зацікавлені бачити вихід з нього (це, як правило, також прискорить, grepоскільки не потрібно аналізувати весь файл, але в цьому випадку це робить дуже мало різниця в швидкості, оскільки файл настільки малий).
Коротко:
#!/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
Ви також можете використати тест pingбезпосередньо, усунувши необхідність в одному з проміжних файлів (а також позбувшись іншого проміжного файлу, який дійсно коли-небудь містить марку дати):
#!/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
В обох варіантах вищезазначеного сценарію я вирішу вийти з циклу, коли не вдалося дістатись до хоста, просто щоб мінімізувати кількість відправлених електронних листів. Замість цього ви можете замінити на, breakнаприклад, на sleep 10mщось, якщо ви очікуєте, що сервер з часом з'явиться знову.
Я також трохи переробив варіанти, які використовуються, pingоскільки -i 1не має великого сенсу -c 1.
Коротше (якщо ви не хочете, щоб він продовжував надсилати електронні листи, коли хост недоступний):
#!/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
Як робота з хроном, що працює щохвилини (продовжуватиме надсилати електронні листи щохвилини, якщо сервер продовжує працювати):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
:? Мені було б сенсом, що це крапка з комою;...