Задача
Необходимо контролировать работу каналов связи на удаленных точках (филиалах) и вести централизованную статистику по следующим параметрам:
- Время отклика и потери до произвольных хостов (например до шлюзов провайдеров)
- Объемы прокачанного трафика и нагрузки на каналы
Метод сбора и агрегирования статистики
Статистику будем получать, подключаясь к удаленным хостам на базе OS Linux Ubuntu через SSH протокол. Затем на удаленном хосте запускаем пинг-флуд на несколько десятков пакетов, а затем парсим результат (среднее значение отклика и процент потерь пакетов). Кроме этого снимаем значения счетчиков принятого и переданного трафика на контролируемых интерфейсах.
Всю собранную информацию сохраняем в базе mysql на сервере статистики. Таким образом на стороне клиента достаточно иметь установленный SSH сервер.
Получение данных
Установка компонентов
Установим компоненты
apt-get install mysql-server mysql-client sshpass
Создадим каталог и подготовим базу данных
mkdir /etc/mystathost nano /etc/mystathost/createdb.sql
Напишем запрос на создание базы
USE mystathost; CREATE TABLE pinggw ( datetime DATETIME, hostip VARCHAR(20), hosteth VARCHAR(10), hostgwip VARCHAR(20), pinglost TINYINT, pingavg FLOAT(3), trafrx BIGINT, traftx BIGINT); # Тут назначим права и разрешим удаленное подключение к базе # Пользователь mystathost # Пароль mYs1Pa$swD grant usage on *.* to mystathost@localhost identified by 'mYs1Pa$swD'; grant all privileges on mystathost.* to mystathost@localhost; exit
Создадим новую базу mystathost
mysqladmin create mystathost -p
Выполним запрос на создание структуры и прав.
mysql -p < /etc/mystathost/createdb.sql
Структура базы готова.
Заполнение базы
Создадим список доступа к удаленным серверам и контролируемых на них каналов. Каждый канал записывается одной строкой с разделением значений знаком ; (точка с запятой) в следующей последовательности
- Адрес сервера для подключения по SSH;пользователь SSH;пароль SSH;Имя контролируемого интерфейса;Адрес, который будем пинговать
nano /etc/mystathost/ping-hosts
100.100.100.100;root;123456;eth1;100.100.100.1 100.100.100.100;root;123456;eth0;192.168.0.100
Для каждого канала отдельная строка, даже если сервер один и тот-же. Например можно проверять как внешние так и внутренние каналы филиала.
nano /etc/mystathost/pinggw
#!/bin/bash
########### Параметры #############
dbuser=mystathost
dbpass=mYs1Pa$swD
dbname=mystathost
dbtable=pinggw
pwdhosts=/etc/mystathost/ping-hosts
###################################
exec 10<$pwdhosts
while read line <&10 ; do
IFS=";"
set -- $line
hostip=$1
hostus=$2
hostpw=$3
hosteth=$4
hostgwip=$5
if [ "${line}" != "" ]
then
pingrez=`sshpass -p $hostpw ssh -o StrictHostKeyChecking=no $hostus@$hostip \
ping -I $hosteth -f $hostgwip -c 100 -s 32|grep -o -P "\d+(?=% packet loss)|\d+\.\d+(?=/\d+.\d+/\d+.\d+ ms,)"|tr "\n" "|"`
pinglost=`echo $pingrez|awk -F "|" '{print $1}'`
pingavg=`echo $pingrez|awk -F "|" '{print $2}'`
trafif=`sshpass -p $hostpw ssh -o StrictHostKeyChecking=no $hostus@$hostip cat /sys/class/net/$hosteth/statistics/rx_bytes /sys/class/net/$hosteth/statistics/tx_bytes|tr "\n" "|"`
trafrx=`echo $trafif|awk -F "|" '{print $1}'`
traftx=`echo $trafif|awk -F "|" '{print $2}'`
datetime=`date +"%Y/%m/%d %T"`
mysql -u$dbuser -p$dbpass -D $dbname -e "INSERT INTO $dbtable (datetime,hostip,hosteth,hostgwip,pinglost,pingavg,trafrx,traftx) \
values ('$datetime','$hostip','$hosteth','$hostgwip','$pinglost','$pingavg','$trafrx','$traftx');"
# echo "`date`;$hostip;$hosteth;$hostgwip;$pinglost;$pingavg;$trafrx;$traftx"
fi
done
Анализ данных
Статистика стабильности канала
use mystathost;
set @rx:=0;
set @trx:=0;
set @dateprev:=now();
select
datetime,
hostip,
hosteth,
hostgwip,
pinglost,
pingavg,
round(rxt/secint/1024*8,2) as RxKbps,
round(trxt/secint/1024*8,2) as TxKbps
from
(select
UNIX_TIMESTAMP(datetime)-@dateprev as secint,
@dateprev:=UNIX_TIMESTAMP(datetime) as ut,
trafrx-@rx as rxt,traftx-@trx as trxt,
@rx:=trafrx,
@trx:=traftx,
datetime,
hostip,
hosteth,
hostgwip,
pinglost,
pingavg
from pinggw
where hostgwip = "95.143.8.33"
and hostip='10.0.34.1'
and datetime >= '2012/06/02'
and datetime <= '2012/06/03'
order by datetime)
as math1;