Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование в *nix (http://forum.oszone.net/forumdisplay.php?f=35)
-   -   [решено] Автоматическое изменение маршрутов (http://forum.oszone.net/showthread.php?t=218237)

El Scorpio 18-10-2011 03:15 1775813

Автоматическое изменение маршрутов
 
Добрый день, прошу помощи в решении следующей проблемы
На работе есть прокси-сервер и два канала связи:
172.25.46.1 - спутниковый модем с большим лимитом предоплаченного трафика и очень большим пингом (около секунды)
172.25.46.254 - ADSL-модем с быстрым пингом, малым лимитом и периодической нестабильностью соединения.

Также есть ряд сайтов, созданных с применением новейших откатно-распилочных технологий. Эти сайты содержат множество скриптов, которые генерируют множество мелких запросов, каждый из которых за счёт большого пинга выполняется нецензурное количество времени.
Можно было бы просто прописать на прокси маршруты через DSL, но это соединение в нашей сельской местности временами работает ещё медленее (или не работает вовсе). В связи с чем планирую написать скрипт, который будет периодически мониторить DSL и переключать маршруты.

Основной алгоритм такой
1. Пинг маршрутизаторов обоих провайдеров и сравнение результатов
2. Если результат DSL лучше, то добавление маршрутов к сайтам по списку (из файла)
3. Если результат DSL хуже, то удаление маршрутов к сайтам по списку (из файла)

По первому пункту. Команда ping выдаёт следующий результат
Цитата:

11 packets transmitted, 10 received, 9% packet loss, time 10852ms
rtt min/avg/max/mdev = 789.661/1015.057/1258.212/156.293 ms, pipe 2
Указанный результат выводится в файл (на RAM-диск, дабы жёсткий до дыр не протереть :) )
Как выделить из этого процент потерянных пакетов и среднее время передачи?

P.S.
man sed прошу не писать...

PhilB 18-10-2011 16:42 1776202

Цитата:

Цитата El Scorpio
Как выделить из этого процент потерянных пакетов и среднее время передачи? »

Конечно решение не идеально, но работает.
Процент потерянных пакетов:
Цитата:

cat 1 | sed 's/[^0-9 ]//g;q' | awk '{print $3;}'
Среднее время передачи:
Цитата:

cat 1 | sed 's/[^0-9 ]//g;q' | awk '{print $4;}'
где 1 - имя файла с результатом пинга.

El Scorpio 20-10-2011 09:06 1777537

PhilB, спасибо. Правда, во второй строке была небольшая ошибка, вызванная использованием символа '/' для разделения цифр. Пришлось добавить дополнительную замену

В общем, получилось следующее
читать дальше »
Код:

#!/bin/bash

# Адрес маршрутизатора второго канала связи
gateway=192.168.1.254
# Адрес маршрутизатора второго провайдера
provider=*.*.*.*
# Адрес сервера в сети интернет, по которому проводится проверка
testserver=8.8.8.8
# Максимально допустимое время прохождения сигнала по второму каналу (в микросекундах)
maxpingtime=500000
# Максимально допустимый процент потери пакетов
maxpinglost=50
# Количество пакетов, используемых для проверки прохождения сигнала
countping=10
# Имя временного файла, в который выводятся результаты проверки (создаётся на RAM-диске)
testpingfile=/tmp/ramdrive/testping
# Имя временного файла, наличие которого означает изменение маршрутов (создаётся на RAM-диске)
usingroutesfile=/tmp/ramdrive/chroutelock
# Имя файла протокола переключения маршрутов
logfile=/var/log/chroute.log
# Флаг хорошей связи (пустое значение означает ложность)
goodlink=
# Файл списка сайтов, работа с которыми будет выполняться по дополнительному каналу (автоматически создаётся при необходимости)
newfilehostlist=/etc/chroute/hosts.lst
[ -a $newfilehostlist ] || touch $newfilehostlist
# Копия файла списка сайтов на RAM-диске (автоматически создаётся при необходимости)
oldfilehostlist=/tmp/ramdrive/chroutehosts.lst
[ -a $oldfilehostlist ] || touch $oldfilehostlist
# Список новых сайтов
newhostlist=$(cat $newfilehostlist | grep -v \#)
# Список действующих сайтов
hostlist=$(cat $oldfilehostlist | grep -v \#)
echo $newhostlist
echo $hostlist

## Функция проверки качества линии связи
testroute()
{
  route add -host $testserver gw $gateway metric 1
  ping $testserver -c $countping | tee $testpingfile 2>&1
  route del -host $testserver
  testpinglost=$(grep "packets transmitted" $testpingfile | sed 's/[^0-9 ]//g;q' | awk '{print $3;}')
  testpingtime=$(grep "rtt min/avg/max/mdev" $testpingfile | sed 's%\/%\ %g' | sed 's/[^0-9 ]//g;q' | awk '{print $2;}' )
  if [[ $testpinglost -gt $maxpinglost ]]
  then
      echo "Обнаружено $testpinglost потерянных пакетов, связь по данному каналу неустойчива"
  elif [[ $testpingtime -gt $maxpingtime ]]
  then
      echo "Время прохождения пакетов по данному каналу $testpingtime превышает разрешённое $maxpingtime"
  else
      goodlink=true
      echo "Канал связи работает"
  fi
}

## Функция добавления маршрутов по списку $hostlist
addroutes()
{
  for hostname in $hostlist
  do
      echo "Добавляется маршрут к $hostname"
      route add -host $hostname gw $gateway metric 1
  done
  touch $usingroutesfile
}

## Функция удаления маршрутов по списку $hostlist
delroutes()
{
  for hostname in $hostlist
  do
      echo "Удаляется маршрут к $hostname"
      route delete -host $hostname
  done
  rm $usingroutesfile
}

## Функция обновления маршрутов
syncroutes()
{
# Если связь была хорошая, то удалить старые маршруты
  [ -a $usingroutesfile ] && delroutes
# Обновить список маршрутов (во временном файле и в памяти)
  if [ -a $newfilehostlist ]
  then
      cp $newfilehostlist $oldfilehostlist
  else
      rm $oldfilehostlist
  fi
  hostlist=$newhostlist
# Если связь хорошая, то добавить новые маршруты
  [ $goodlink ] && addroutes
}

## Основной код программы

# добавляется маршрут до узла провайдера (при необходимости)
[[ $( route -n | grep $provider | wc -l ) > 0 ]] || route add -host $provider gw $gateway metric 1

testroute
if [[ "$hostlist" != "$newhostlist" ]]
then
  echo $(date +%F\ %T)": Изменён файл списка сайтов, производится обновление маршрутов" | tee -a $logfile
  syncroutes
elif [[ $goodlink  &&  ! -a $usingroutesfile ]]
then 
  echo $(date +%F\ %T)": Связь по дополнительному каналу работает, производится добавление маршрутов" | tee -a $logfile
  addroutes
elif [[ ! $goodlink && -a $usingroutesfile ]]
then
  echo $(date +%F\ %T)": Проблемы связи по дополнительному каналу, производится удаление маршрутов" | tee -a $logfile
    delroutes
fi

exit



Если кто найдёт и поможет исправить ошибку, буду очень признателен.
Желающим использовать этот скрипт в работе, использование и дальнейшую модификацию разрешаю

El Scorpio 25-10-2011 07:56 1781059

Упс, нашёл баг в функции delroutes , из-за которого не удаляются маршруты к некоторым сайтам

Я исходил из того, что команда route del -host $hostname определяет IP хоста по его имени, а затем удаляет из таблицы маршрутизации строку с соответствующим IP и маской 255.255.255.255.
Однако всё словно происходит с точностью до наоборот: команда определяет имена хостов для всех строк таблицы маршрутизации, а затем ищет среди них нужную. При этом, если для какого-то адреса поиск в "обратной зоне DNS" возвращает другое (!!!) имя сайта (например www.XXXX.ru вместо XXXX.ru), то вместо удаления выводится сообщение об отсутствии указанного маршрута.

Значит нужно удалять маршрут по IP-адресу сайта, а для этого его нужно сначала определить. Например, вот так:
Код:

ip=$(ping $hostname -c 1 | head -n 1 | sed ... )
# в результате получается
# PING имя.сайта (ip.адрес.сайта) 56(84) bytes of data.

Какие параметры для команды sed указать, чтобы получить значение между первыми скобками?

PhilB 25-10-2011 20:35 1781597

Вроде так
Код:

sed '/[^(]*(\([^ ]*\)).*/s//\1/g'

El Scorpio 03-11-2011 03:38 1787754

Итак, предлагаю вашему вниманию исправленную и доработанную версию скрипта, который автоматически переключает маршруты к определённым сайтам. Распространение приветсвуется

читать дальше »
Код:

#!/bin/bash

# Адрес маршрутизатора второго канала связи
gateway=192.168.1.254
# Адрес маршрутизатора второго провайдера
provider=x.x.x.x
# Адрес сервера в сети интернет, по которому проводится проверка
testserver=8.8.8.8
# Максимально допустимое время прохождения сигнала по второму каналу (в микросекундах)
maxpingtime=1000000
# Максимально допустимый процент потери пакетов
maxpinglost=50
# Количество пакетов, используемых для проверки прохождения сигнала
countping=10
# Имя временного файла, в который выводятся результаты проверки (создаётся на RAM-диске)
testpingfile=/tmp/ramdrive/testping
# Имя временного файла, наличие которого означает изменение маршрутов (создаётся на RAM-диске)
usingroutesfile=/tmp/ramdrive/chroutelock
# Имя файла протокола переключения маршрутов
logfile=/var/log/chroute.log
# Флаг хорошей связи (пустое значение означает ложность)
goodlink=
# Файл списка сайтов, работа с которыми будет выполняться по дополнительному каналу newfilehostlist=/etc/chroute/hosts.lst
# если файл отсутствует, то создаётся автоматически
[ -a $newfilehostlist ] || touch $newfilehostlist
# Копия файла списка сайтов на RAM-диске
oldfilehostlist=/tmp/ramdrive/chroutehosts.lst
# если файл отсутствует, то создаётся автоматически
[ -a $oldfilehostlist ] || touch $oldfilehostlist
# Список новых сайтов. Записи добавляются построчно. Лишние можно закомментировать "решёткой" 
newhostlist=$(cat $newfilehostlist | grep -v \#)
# Список действующих сайтов
hostlist=$(cat $oldfilehostlist | grep -v \#)

echo $newhostlist
echo $hostlist

## Функция проверки качества линии связи
testroute()
{
# добавление временного маршрута к тестовому серверу и проверка прохождения сигнала
        route add -host $testserver gw $gateway metric 1
        ping $testserver -c $countping | tee $testpingfile 2>&1
        route del -host $testserver
# выделение значений из результатов пинга
        testpinglost=$(grep "packets transmitted" $testpingfile | sed 's/[^0-9 ]//g;q' | awk '{print $3;}')
        testpingtime=$(grep "rtt min/avg/max/mdev" $testpingfile | sed 's%\/%\ %g' | sed 's/[^0-9 ]//g;q' | awk '{print $2;}' )
# если процент потерянных пакетов превышает максимальный
        if [[ $testpinglost -gt $maxpinglost ]]
        then
                echo "Обнаружено $testpinglost потерянных пакетов, связь по данному каналу неустойчива"
# если среднее время прохождения сигнала превышает максимальное
        elif [[ $testpingtime -gt $maxpingtime ]]
        then
                echo "Время прохождения пакетов по данному каналу $testpingtime превышает разрешённое $maxpingtime"
        else
                goodlink=true
                echo "Канал связи работает"
        fi
}

## Функция добавления маршрутов по списку $hostlist
addroutes()
{
        for hostname in $hostlist
        do
                echo "Добавляется маршрут к $hostname"
                route add -host $hostname gw $gateway metric 1
        done
        touch $usingroutesfile
}

## Функция удаления маршрутов по списку $hostlist
delroutes()
{
        for hostname in $hostlist
        do
                echo "Удаляется маршрут к $hostname"
# При выполнении "route delete -host" производится поиск имени хоста среди списка имён.
# Список имён формируется в процессе обратной расшифровки адресов в имена.
# Если в результате обратной расшифровки возвращается имя, отличное от исходного,
# то команда удаления найти маршрут по исходному имени не может
# Посему приходится сначала определять IP-адрес по имени сайта, а потом удалять маршрут по этому IP-адресу
                ip=$(ping $hostname -c 1 | head -n 1 | sed '/[^(]*(\([^ ]*\)).*/s//\1/g')
                echo "Для сайта $hostname IP-адрес равен $ip"
                route del -host $ip
        done
        rm $usingroutesfile
}

## Функция обновления маршрутов
syncroutes()
{
# Если связь была хорошая, то удалить старые маршруты
        [ -a $usingroutesfile ] && delroutes
# Обновить список маршрутов (во временном файле и в памяти)
        if [ -a $newfilehostlist ]
        then
                cp $newfilehostlist $oldfilehostlist
        else
                rm $oldfilehostlist
        fi
        hostlist=$newhostlist
# Если связь хорошая, то добавить новые маршруты
        [ $goodlink ] && addroutes
}

## Основной код программы

# добавляется маршрут до узла провайдера (если отсутствует)
[[ $( route -n | grep $provider | wc -l ) > 0 ]] || route add -host $provider gw $gateway metric 1

testroute
if [[ "$hostlist" != "$newhostlist" ]]
then
        echo $(date +%F\ %T)": Изменён файл списка сайтов, производится обновление маршрутов" >> $logfile
        syncroutes
# Если связь хорошая и нет файла-флага добавленных маршрутов
elif [[ $goodlink  &&  ( ! -a $usingroutesfile ) ]]
then       
        echo $(date +%F\ %T)": Связь по дополнительному каналу работает, производится добавление маршрутов" >> $logfile
        addroutes
# Если связь плохая и есть флаг-файл добавленных маршрутов
elif [[ ! $goodlink && ( -a $usingroutesfile ) ]]
then
        echo $(date +%F\ %T)": Проблемы связи по дополнительному каналу, производится удаление маршрутов" >> $logfile
        delroutes
fi
# Комбинации состояний "связь хорошая, маршруты уже добавлены" и "связь плохая, маршруты уже удалены" действий не требуют

exit



Монтирование RAM-диска производится через файл /etc/fstab
Код:

tmpfs        /tmp/ramdrive                                        tmpfs nosuid,nodev,noatime,nodiratime 0 0


Время: 01:13.

Время: 01:13.
© OSzone.net 2001-