График загрузки сети

Первый способ с использованием протокола SNMP (Symple Network Management Protocol.

Устанавливаем из портов /usr/ports/net-mgmt/net-snmp и /usr/ports/databases/rrdtool. Текущая версия net-snmp 5.3.2_1, rrdtool 1.2.26. При установке rrdtool выбираем опцию “Use Perl” (по умолчанию).

# cd /usr/ports/databases/rrdtool
# make install clean
# cd /usr/ports/net-mgmt/net-snmp
# make install clean

После инсталляции можно посмотреть примеры перловых скриптов /usr/local/share/examples/rrdtool. Первым делом нужно создать конфиг snmpd.conf, делается он с помощью скрипта snmpconf в интерактивном режиме:

# snmpconf -i
 1: snmpd.conf
 2: snmptrapd.conf
 3: snmp.conf
Выбираем snmpd.conf – жмем на 1, появляется следуещее меню выбора:
 1: System Information Setup
 2: Access Control Setup
 3: Trap Destinations
 4: Monitor Various Aspects of the Running Host
 5: Extending the Agent
 6: Agent Operating Mode
Выбираем System Information Setup – жмем на 1, появляется:
1: The [typically physical] location of the system.
2: The contact information for the administrator
3: The proper value for the sysServices object.
Выбираем 1 – физическое расположение сервера, вводим Kiev, тут можно вводить что угодно и нажимаем enter. Далее выбираем 2 – контакты админа, пишем admin@domain -> enter. Выбираем 3 пункт – тут спросят о сервисах, которые на сервере работают, варианты ответов 1-да,0-нет (я на все вопросы отвечал 1). В этом меню мы ответили на все вопросы пишем finished и возвращаемся на уровень выше, выбираем Access Control Setup (2) – кто имеет доступ и выидим:
1: a SNMPv3 read-write user
2: a SNMPv3 read-only user
3: a SNMPv1/SNMPv2c read-only access community name
4: a SNMPv1/SNMPv2c read-write access community name
Выбираем 3-й пункт, т.к. нам нужно только считывать информацию, тут попросят указать community name, указываем, например, comm_domain -> enter, далее спросят кто будет принимать данные, пишем localhost -> enter, на третий вопрос жмем enter и выходим из этого подменю, пишем finished. Теперь выбираем 6-й пункт Agent Operating Mode:
1: Should the agent operate as a master agent or not.
2: The system user that the agent runs as.
3: The system group that the agent runs as.
4: The IP address and port number that the agent will listen on.
Выбираем 4-й пункт – на каком порту и IP будет работать агент – пишем localhost -> enter -> finished -> enter -> finished -> enter -> quit -> enter. Конфиг создан в /usr/local/share/snmp, теперь его нужно скопировать в /usr/local/etc/snmp, предварительно создав эту директорию, добавить в /etc/rc.conf snmpd_enable=”YES” и запустить из /usr/local/etc/rc.d:

 # mkdir /usr/local/etc/snmp
 # cp /usr/local/share/snmp/snmpd.conf /usr/local/etc/snmp
 # echo ‘snmpd_enable=”YES”‘ >> /etc/rc.conf
 # /usr/local/etc/rc.d/snmpd start
 Starting snmpd
 # /usr/local/etc/rc.d/snmpd status
 snmpd is running as pid 43831.
 # sockstat -4|grep snmp
 root snmpd 43831 9 tcp4 *:199 *:*
 root snmpd 43831 10 udp4 *:161 *:*

Мы видим, что все успешно поднялось и работает, теперь нужно проверить, что отдает наш snmpd, для этого служит команда snmpwalk:

# snmpwalk -c comm_domain -v 1 localhost

На эту команду snmpd должен выдать большой список поддерживаемых параметров, нас больше будет интересовать базы сетевых интерфейсов, нужно определиться какая именно база отвечает за интерфейс. У меня внешний интерфейс ed0, внутренний -em0.

# snmpwalk -c comm_domain -v 1 localhost | grep IF-MIB::ifDescr
 IF-MIB::ifDescr.1 = STRING: em0
 IF-MIB::ifDescr.2 = STRING: fxp0
 IF-MIB::ifDescr.3 = STRING: em1
 IF-MIB::ifDescr.4 = STRING: ed0
 IF-MIB::ifDescr.5 = STRING: plip0
 IF-MIB::ifDescr.6 = STRING: lo0
 HOST-RESOURCES-MIB::hrSWRunParameters.31946 = STRING: “IF-MIB::ifDescr”

Счетчики пакетов пишутся в IF-MIB::ifInOctets.x и IF-MIB::ifOutOctets.x, где x – номер, соответствующий интерфейсу в IF-MIB::ifDescr.x. Счетчик для ed0 – IF-MIB::ifInOctets.4 и IF-MIB::ifOutOctets.4, для em0 – IF-MIB::ifInOctets.1 и IF:MIB::ifOutOctets.1. Эти данные нам пригодятся в дальнейшем. Теперь нам нужно создать базу RRD, куда будут заноситься данные от snmpd. Базу создаем скриптом:

#!/bin/sh

if [ ! $1 ];
 then
 echo “Please specify a rrd filename.”
 exit 1
 fi

RRDBNAME=$1

rrdtool create ${RRDBNAME} -s 60 \
 DS:input:DERIVE:120:0:U \
 DS:output:DERIVE:120:0:U \
 RRA:AVERAGE:0.5:1:1500 \
 RRA:MAX:0.5:1:1500 \
 RRA:AVERAGE:0.5:5:600 \
 RRA:MAX:0.5:5:600 \
 RRA:AVERAGE:0.5:30:700 \
 RRA:MAX:0.5:30:700 \
 RRA:AVERAGE:0.5:120:800 \
 RRA:MAX:0.5:120:800 \
 RRA:AVERAGE:0.5:1440:800 \
 RRA:MAX:0.5:1440:800 \
 RRA:LAST:0:1:1

Не забываем дать скрипту права на исполнение chmod +x. В качестве параметра необходимо указывать название файла, например external.rrd. В данном примере будут мониториться 2 интерфейса внешний в нутренний, название баз для гих external.rrd и internal.rrd. -s – с какам интервалом в секунду будут вноситься данные в базу. По умолчанию, если не указывать этого параметра будет установлено 300 сек (5мин), мне необходимо чаще, поэтому установил 60 сек (1 мин).
Формат записи DS:
DS:ds-name:GAUGE | COUNTER | DERIVE | ABSOLUTE:heart-beat:min:max
DS (Data Source) описывает источники данных, которые определяют какие действия с данными необходимо сделать. ds-name: Input и output – имя источника базы, DERIVE – тип источника базы, при поступлении данных берется разница между отсчетами и делится на значение step (-s), тоже самое делает и COUNTER, но DERIVE не вносит данных выходящих за пределы, более детально лучше почитать в манах. Значение 120 сек (heart-beat) -это максимальное время на которое могут отстоять соседние отсчеты, если оно будет превышено, то значения будут считаться неопределенными (unknow). Далее указано 0 -минимальное значение и U -максимальное, в данном случае неизвестно какой верхний предел, поэтому указано это значение.
Формат записи RRA:
RRA:AVERAGE | MIN | MAX | LAST:xff:steps:rows
RRA (Round Robin Archive) хранит числовой ряд, полученный путем консолидации значений значений PDP (primary data points) – тех значений, который вводятся в базу после их интерпретации, в данном случай функцией DERIVE. Следующим параметром RRA указывается функция консолидации, может применяться AVERAGE, MIN, MAX, LAST. Она определяет какие действия над числами (PDP) необходимо выполнить, чтобы получить результат, который будет храниться в RRA. Этот результат называется CDP (consolidated dat point). xff = 0.5 – доля неопределенных PDP из интервала консолидации, при которой возможно вычислить CDP. step – количество PDP на которые налаживается функция консолидации и в результате получается 1CDP. Rows – количество значений CDP, хранимых в RRA. В базе может быть несколько RRA, таким образом данные будут храниться за достаточно большой интервал и при этом объем бызы будет неизменен.

Размер интервала можно самому выбрать, для примера можно взять настройки пакета MRTG, который использует 600 5 минутных отсчетов, 600 30-минутных отсчетов, 600 2-х часовых отсчетов, 732 дневных отсчета. У меня период ввода в базу данных 1мин, поэтому данные отсчетов необходимо пересчитать. Итак: первый RRA должен хранить одноминутные отсчеты 24 часа, 5-минутные 2 дня, 30-минутные 2 недели, 2-х часовые 2 месяца, 1-дневные 2 года. Вычисляем step и rows. step = необходимый интервал деленный на интевал ввода данных в базу (60сек). rows = интервал, необходимый для хранения данных деленный на step. Все вычисления в минутах. Получаем:

 1RRA: step = 1/1 = 1 (1мин), rows = 24ч*60/1 = 1440 ~ 1500
 2RRA: step = 5/1 = 5 (5мин), rows = 2*24*60/5 = 576 ~ 600
 3RRA: step = 30/1 = 30 (30мин), rows = 2*7*24*60/30 = 672 ~ 700
 4RRA: step = 120/1=120 (2часа), rows = 2*31*24*60/120 = 744 ~ 800
 5RRA: step = 1440/1 =1440 (1день), rows = 2*366*24*60/1440 = 732 ~800

База у нас создана, теперь нужно в нее вносить данные, создаем скрипт:

#!/bin/sh

#IF-MIB::ifDescr.1 = STRING: em0
 EXT_DATA_IN=”IF-MIB::ifInOctets.1″
 EXT_DATA_OUT=”IF-MIB::ifOutOctets.1″

#IF-MIB::ifDescr.4 = STRING: ed0
 INT_DATA_IN=”IF-MIB::ifInOctets.4″
 INT_DATA_OUT=”IF-MIB::ifOutOctets.4″

SNMPGET=”/usr/local/bin/snmpget -v 1 -c comm_domain -Oqv localhost”

RRDUPD=”/usr/local/bin/rrdtool update”

${RRDUPD} /usr/local/etc/rrdtool/db/external.rrd N:$(expr -e $(${SNMPGET} ${INT_DATA_IN}) \* 8):$(expr -e $(${SNMPGET} ${INT_DATA_OUT}) \* 8)
 ${RRDUPD} /usr/local/etc/rrdtool/db/internal.rrd N:$(expr -e $(${SNMPGET} ${EXT_DATA_IN}) \* 8):$(expr -e $(${SNMPGET} ${EXT_DATA_OUT}) \* 8)

В скрипте снимаются спомощью snmpget данные с snmpd и пишутся в external.rrd и internal.rrd. Данные умножаются на 8, т.к. нам необходимо получить значения в битах, snmpd собирает их в байтах. Скрипт помещаем в /etc/crontab с интервалом запуска 1 минута и не забываем дать скрипту права на исполнение chmod +x:

*/1 * * * * root /usr/local/etc/rrdtool/if_octets.sh

Теперь нам остается только данные базы отобразить на на графиках. Помещаем следущий скрипт в крон с интервалом 1мин:

#!/bin/sh

/usr/local/bin/rrdtool graph /usr/local/www/mon/png/ext_2h.png \
 –width 450 \
 –height 300 \
 –start -2h \
 –end now \
 –title “Network External(ed0) 2 hour” \
 –rigid –vertical-label bits/sec \
 DEF:input=/usr/local/etc/rrdtool/db/external.rrd:input:AVERAGE \
 DEF:output=/usr/local/etc/rrdtool/db/external.rrd:output:AVERAGE \
 VDEF:maxin=input,MAXIMUM \
 VDEF:maxout=output,MAXIMUM \
 VDEF:avgin=input,AVERAGE \
 VDEF:avgout=output,AVERAGE \
 VDEF:lastout=output,LAST \
 VDEF:lastin=input,LAST \
 AREA:input#00FF00:”In ” \
 GPRINT:maxin:”Max = %.2lf %sb/s” \
 GPRINT:avgin:”Avg = %.2lf %sb/s” \
 GPRINT:lastin:”Last = %.2lf %sb/s\j” \
 LINE1:output#0000FF:”Out” \
 GPRINT:maxout:”Max = %.2lf %sb/s” \
 GPRINT:avgout:”Avg = %.2lf %sb/s” \
 GPRINT:lastout:”Last = %.2lf %sb/s\j”

В этом скрипте командой rrdtool graph создается файл ext_2h.png, разрешением 450*300, интервалом 2 часа. В VDEF прописываются переменные, которые будут отображаться на графиках, AREA – цвет главного заливки, LINE1 – отображение указанным цветом исходящего трафика, GPRINT – вывод на графики значения переменных, заданных в VDEF. Это пример создания 2-х часового графика, меняя значение –start можно просматривать графика за любой период. Теперь отобразим эти графики в виде html. Создадим алиас в апаче и положим его /usr/local/etc/apache22/Includes:

Alias /mon “/usr/local/www/mon”
 <Directory “/usr/local/www/mon”>
 AddDefaultCharset windows-1251
 AllowOverride All
 Order deny,allow
 </Directory>

Создадим директорию /usr/local/www/mon и положим туда index.html:

<html>
 <head>
 <meta http-equiv=Content-Type content=”text/html; charset=koi8-r”>
 <title> Network traffic.</title>
 </head>
 <body bgcolor=”DDEEDD” text=”000000″ link=”0000FF” alink=”FF0000″ vlink=”0000FF”>
 <img src=”png/ext_2h.png” border=1 />
 <img src=”png/int_2h.png” border=1 />
 </BODY>
 </HTML>

Теперь, зайдя на http://localhost/mon/index.html увидим графики загрузки внешнего и внутреннего интерфейсов за последние 2 часа. Графики строить можно и с помощью rrdcgi, тогда не нужно каждую минуту генерировать новый png, кому интересно читаем маны.

Второй способ снятия статистики – использование счетчиков в ipfw. прописываем в /etc/rc.firewall следующее:

/sbin/ipfw add 1 count ip from 1.1.1.1 to any out xmit ed0
/sbin/ipfw add 2 count ip from any to 1.1.1.1 in recv ed0

Эти правила будут считать исходящие и входящие пакеты, прошедшие через внешний интерфейс ed0, 1.1.1. – его интерфейсный IP. Создаем скрипт и через крон запускаем его каждую минуту, он будет добавлять значения в базу полученные от счетчиков ipfw:

#!/bin/sh
 out=`ipfw show 1 | awk ‘{print $3}’`
 in=`ipfw show 2 | awk ‘{print $3}’`
 /usr/local/bin/rrdtool update /usr/local/etc/rrdtool/db/external.rrd N:$in:$out

Значения будут в байтах, чтобы перевести их в биты умножаем на 8, это можно сделать в этом скрипте или добавить в скрипт описанный выше, который рисует графики переменную CDEF:

“CDEF:inbits=in,8,*” \
“CDEF:outbits=out,8,*”

А далее все также как и было описано, создаем png, добавляем в апач алиас, создаем html и смотрим графики.

Источник информации:
1.  http://bog.pp.ru/map_full.html#linux
2.  http://silinio.webhost.ru/net-snmp-comms.html
3.  http://ru.gentoo-wiki.com/Мониторинг_работы_системы
4.  http://bozza.ru/?c=231&p=content
5.  http://www.nestor.minsk.by/sr/2004/05/40516.html

© mick, 2008.

Embark on the gaming conquest at Glory's ultimate gaming challenge , where every victory is legendary.