Коли 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 )
:
? Мені було б сенсом, що це крапка з комою;
...