Определение момента, когда поднялся VPN тоннель.
Продолжаю начатое тут.
Обычно тоннель поднимается командой
pppd call providername
где providername
– файл настроек соединения в /etc/ppp/peers
. Команда особого интерактива не дает, а хотелось бы, например, чтоб выводился «прогресс-бар», когда соединение устанавливается, а по прошествии максимального времени ожидания, если соединение так и не поднялось, выводилось сообщение о таймауте. Если соединение поднялось до истечения таймаута – выводилось сообщение об успехе. Скрипту будет передаваться единственный параметр – имя необходимого файла настроек соединения из
/etc/ppp/peers
1. Проверить собственные параметры, и если файл настроек не указан – выдать соответствующее сообщение и прекратить работу.
2. Проверить наличие переданного файла настроек
3. Проверить, не поднято ли уже это соединение, если поднято – выдать сообщение и прекратить работу
4. Проверить параметр настройки
unit
– номер будущего интерфейса ppp. Если его нет – найти первый свободный (его и использует pppd
). Если параметр unit
присутствует, то проверить, свободен ли он, если нет – найти первый свободный.5. Запустить установку соединения.
6. В цикле проверять, установилось ли оно, или истек заданный таймаут
7. По завершению цикла оповестить пользователя об успехе или истечении таймаута.
Главный недочет предыдущей версии скрипта - жестко заданная проверка наличия соединения командой
ping
, после получения сведений об установленном соединении из вывода команды ifconfig
. Пинговался адрес полученного шлюза. Дело в том, что некоторые провайдеры не позволяют пинговать шлюз, или вообще отключают возможность использования протокола ICMP, поэтому необходимо дать пользователю возможность через параметры командной строки указать, нужно ли использовать дополнительную проверку с помощью ping
и какой адрес в случае необходимости пинговать.Заодно мною были добавлены дополнительные информационные сообщения, а также немного видоизменен основной рабочий цикл.
WTIMEOUT=120 #Максимальное время ожидания
PEERFILE="/etc/ppp/peers/" # имя файла с настройками ppp-соед-я
ADDR="" #адрес, который нужно пинговать
PING=0 #флаг, показывающий включена ли проверка ping
Проверка параметров
#Проверяем параметры
if [ -z "$1" ]; then
echo "USE myconn [-p] [address]";
echo "Options:";
echo " - file in /etc/ppp/peers";
echo "[-p] - use ping check";
echo "[address] - address to ping, default use gateway address";
exit 2;
fi
Если первый параметр пуст (-z
), то выводим сообщения об используемых скриптом параметрах и завершаем работу с кодом завершения 2 (exit 2
). Если параметры заданы выводим пользователю сообщение о том, какое соединение будет использовано:
echo "Connecting to "$1;
Далее проверяем, необходима ли проверка соединения с помощью
ping
, и задан ли адрес, который нужно пинговать. Попутно выдаем пользователю соответствующие сообщения:if [ "$2" = "-p" ]; then #если второй параметр скрипта="-p"
#будем пинговать
PING=1; #устанавливаем флаг включающий проверку
echo -n "Ping test address..."
if [ -n "$3" ]; then #и проверяем задан ли адрес
ADDR=$3; #если да, сохраняем его в переменную
echo $ADDR;
else #иначе будет использован адрес шлюза
echo "Gateway address.";
fi
else
echo "No ping test"
fi
PEERFILE="$PEERFILE""$1";
#Проверяем, есть ли файл
if [ ! -e "$PEERFILE" ]; then
echo "File "$PEERFILE" not found";
exit 1;
fi
В переменную
$PEERFILE
где уже записан путь к файлам настроек соединений, добавим первый параметр ($1
), переданный скрипту. Если файл не существует (! -e
), выводим сообщение об ошибке и завершаем работу.Можно сделать это следующим образом. Когда соединение поднято, pppd висит в памяти, и его вместе с параметрами запуска будет видно в выводе команды
ps
, чем можно и воспользоваться, скормив вывод ps
команде grep
. Останется только подсчитать количество найденных grep
строк, если их будет больше одной (а одна точно будет, т.к. в вывод команды ps
попадет и сама команда grep
с ее параметрами), значит pppd
уже пытается поднять или поднял указанное соединение и можно завершить работу, выдав соответствующее сообщение.Строки
grep
сам и посчитает, достаточно указать ему параметр -c
#Проверяем, не соединено ли уже
#(в списке процессов д.б. 2 строки pppd call NNN, если соединено)
TMPGREP=`ps ax|grep "pppd call $1" -c`
if [ $TMPGREP -gt 1 ]; then
echo "ERROR: $1 already connected"
exit 1;
fi
Для этого достаточно в цикле вызывать команду ifconfig с параметром pppN, где N – проверяемый номер и проверять код возврата ifconfig. Если он 0 (нормальное завершение), такое соединение уже поднято. Если не 0 – информацию о соединении получить не удалось, значит, оно отсутствует. Способ, возможно, кривоват, так что выскажитесь в комментариях, если есть предложить что лучше. Но у меня пока сбоев не было.
#Ищем первый свободный номер для ppp соединения
FIRSTFREE=0;
ifconfig ppp$FIRSTFREE >/dev/null 2>/dev/null
while [ $? -eq 0 ]; do
let "FIRSTFREE = FIRSTFREE+1";
ifconfig ppp$FIRSTFREE >/dev/null 2>/dev/null
done
2>/dev/null
перенаправляет вывод из stderr в нуль-устройство, чтоб не загромождать вывод неизбежными сообщениями об ошибках, когда свободный номер будет найден.Найдем параметр
unit
с помощью grep
, и запишем его значение в переменнуюPPPUNIT=`grep "unit" $PEERFILE`
Удалим из полученной строки слово unit и пробелы с помощью стандартных средств bash
.PPPUNIT=${PPPUNIT//unit/}
PPPUNIT=${PPPUNIT// /}
Если параметр unit
был корректно указан в файле конфигурации соединения, то он будет записан в переменную $PPPUNIT
, если нет – переменная $PPPUNIT
будет пуста.Проверка
Теперь нужно проверить, указан ли параметр
unit
, если не указан, то выдать сообщение о том, что система использует первый свободный, отобразить его и присвоить его значение переменной $PPPUNIT
. Если параметр unit
указан – проверить, свободен ли он (таким же способом, которым мы искали номер первого свободного, только, естественно, без цикла). Если свободен – вывести на экран сообщение об этом, если занят – предупредить пользователя, что будет использован первый свободный номер и присвоить его значение переменной $PPPUNIT
.if [ -z "$PPPUNIT" ]; then
#Если параметр unit не указан, система использует первый
# свободный при поднятии соединения
echo "Parameter 'unit' not found, system use first free
($FIRSTFREE)";
PPPUNIT=FIRSTFREE;
else
#Если указан, то проверить занят он или нет
ifconfig ppp$PPPUNIT >/dev/null 2>/dev/null
if [ $? –eq 0 ]; then #занят
echo “WARNING! Unit #$PPPUNIT is already in use, system use
first free ($FIRSTFREE)";
PPPUNIT=FIRSTFREE;
else #свободен
echo "Unit $PPPUNIT is free. OK."
fi
fi
#устанавливаем соединение
pppd call $1
CONNECTED=0 #флаг
И выведем сообщениеecho -n "Wait ("$WTIMEOUT" secounds): "
Параметр -n
отключает перенос строки в команде echo
, соответственно, следующее сообщение будет выведено на ту же строку.В цикле командой
echo
выводим точку, командой sleep 1
устанавливаем секундную задержку, а далее пытаемся получить из вывода команды ifconfig
строчку с данными об IP, таким же способом и IP шлюза с помощью команды awk
.Если IP получен, проверяем нужна ли проверка с помощью
ping
. Если проверка нужна, то проверяем, задан ли IP для ping
или нужно пинговать полученный IP шлюза, если IP для IP для ping
не задан, устанавливаем его значение равным полученному. Если задан - оставляем таким же, если проверка ping
не нужна вообще, устанавливаем в 1 флаг $CONNECTED в
1 и прерываем цикл.Если проверка
ping
нужна – пытаемся пропинговать ранее заданный IP. Если пинг успешен (код завершения команды ping
будет = 0), то устанавливаем в 1 флаг $CONNECTED
. И прерываем цикл.Если условия не сработали – отнимаем от переменной $
WTIMEOUT
единицу и уходим на следующую итерацию цикла. Цикл продолжается, пока не достигнуто значение времени ожидания =0.Важно: в команде
ping
надо не забыть указать интерфейс, через который будем пинговать. Делается это с помощью ключа -I имя_интерфейса
. Можно также выставить количество посылаемых узлу пакетов в 1 с помощью ключа -c
Например:
ping -I ppp1 -c 1 10.20.4.4
while [ $WTIMEOUT -ge 0 ]; do
echo -n ".";
sleep 1
#***************************************************
#пытаемся получить строчку с IP шлюза
TMPGREP=`ifconfig ppp$PPPUNIT 2>/dev/null|grep "destination"`
if [ -n "$TMPGREP" ]; then #если строчка есть
TMPGREP=`echo $TMPGREP|awk ' {print $6} '` #извлекаем awk IP шлюза
if [ -n "$TMPGREP" ];then #если он не пустой
if [ $PING -eq 1 ]; then #если надо пинговать
if [ -z "$ADDR" ]; then #если адрес не задан - адрес будет шлюза
ADDR=$TMPGREP
fi
ping -c 1 -I ppp$PPPUNIT $ADDR >/dev/null 2>/dev/null #пингуем
if [ $? -eq 0 ]; then # если получилось
CONNECTED=1 #устанавливаем флаг соед-я
break #Прерываем цикл. Ура!!
fi
else #если пинговать не надо
CONNECTED=1 # устанавливаем флаг соед-я
break #Прерываем цикл. Ура!!
fi
fi
fi
#***************************************************
let "WTIMEOUT=WTIMEOUT-1";
done
После выхода из цикла выводим echo
без параметров (чтоб следующие строки выводились с новой), проверяем состояние флага и выводим соответствующее сообщение.if [ $CONNECTED -eq 0 ]
then
echo "Connection timeout over :("
exit 1
else
echo "Connected sucsesseful!"
exit 0
fi
Скрипт на pastebin
Скачать с mega.nz
Куда прикрутил обратный отсчет времени с мельницей, скрестив этот скрипт с вот этим.
Скрипт на pastebin
Скачать с mega.nz