Для контроля состояния линка будем пинговать шлюз провайдера. Утилита ping
, идущая вместе с FreeBSD и Linux, нам не подходит, т.к. не выдает никаких сообщений при отсутствии ответа проверяемого хоста. То есть нам требуется поведение присущее ping
из windows, выводящей в аналогичном случае «timeout
». После недолгих поисков утилита oping
оказалась идеальным кандидатом.
Собственно шаблон скрипта с подробными комментариями:
#!/bin/sh
# $1 - проверяемый IP-адрес
# $2 - режим работы скрипта
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Выходим если не задан проверяемый IP
if [ -z $1 ]; then exit 1; fi
# Проверка режима работы
if [ -z $2 ]
then
# Отслеживание падения линка
# Создаем временный файл для хранения статуса линка
SAVE=$(mktemp)
# Ловим сигнал завершения и удаляем файл статуса
trap 'rm -f $SAVE; exit 0;' INT TERM QUIT
# Пингуем заданный IP-адрес с интервалом в 5 секунд
# и с помощью xargs вызываем самого себя, передавая
# результат пинга и имя файла состояния как параметры
# командной строки.
oping -4 -i 5 $1 | \
sed \
-e '1d' -e '/^--- /d' \
-e '/packets transmitted/d' \
-e '/^$/d' -u | \
xargs -n 1 --delimiter='\n' -I'{}' $0 none check "{}" $SAVE \
>> /var/log/vpn-watchdog.log
# Удаляем файл статуса
rm -f $SAVE
elif [ $2 = check -a ! -z $4 ]
then
# Watchdog
# $3 - результат пинга
# $4 - имя файла состояния
# Получение состояния линка
STATUS=$(echo $3 | grep -oE '(ms|timeout)$')
# Сравнение
if [ ! -z "$STATUS" ]
then
# Определение состояния линка и исключение
# ложного срабатывания
if [ "$STATUS" = timeout -a "$(cat $4)" != $STATUS ]
then
# Реакция на событие
echo -n "$(date +'%Y-%m-%d %H-%M-%S') TIMEOUT - Restarting... "
# Далее идет несколько строк команд
# ...
echo " done!"
fi
# Сохраняем текущее состояние для последующей проверки
echo -n $STATUS > $4
fi
fi
Достоинства данного подхода: не требуется вызывать из крона по расписанию, мониторинг идет непрерывно и, если требуется, время реакции на событие может составить одну-две секунды.