Когда 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
В обоих вариантах сценария, приведенного выше, я выбираю выход из цикла при невозможности связаться с хостом, просто чтобы минимизировать количество отправляемых писем. Вместо этого вы можете заменить на breakeg 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 )
:? Было бы разумно, если бы это была точка с запятой;...