Когда 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
eg 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
Поскольку задание cron выполняется каждую минуту (будет продолжаться отправка писем каждую минуту, если сервер продолжает не работать):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
:
? Было бы разумно, если бы это была точка с запятой;
...