- Введение
- Теория
- Установка
- Интерфейс командной строки
- Мониторинг загрузки процессора
- Мониторинг температуры процессора
- Мониторинг использования памяти
- Заключение
Введение
Думаю, практически каждый системный администратор видел красивые графики, отображающие какие-либо статистические данные за определенный период времени. Одним из примеров таких графиков может служить раздел статистики на этом сайте. Подобные графики можно нарисовать с помощью утилит из пакета RRDtool. RRDtool - набор утилит для работы с кольцевой базой данных (RRD), предназначенных для хранения, обработки и визуализации динамических (изменяющихся во времени) последовательностей данных, таких как сетевой трафик, температура, загрузка процессора и т.п. RRDtool очень легко интегрировать в bash скрипты, также есть привязки в виде библиотек к языкам Perl, Python, Ruby. Все действия я буду проводить на машине с ОС FreeBSD 8.3.Теория
RRD - это кольцевая база данных. Главная особенность данной БД заключается в том, что она всегда имеет фиксированный размер. То есть когда, будет достигнут конец в каком-нибудь поле в такой БД, то данные будут записываться в самое начало, тем самым, затирая предыдущие. В RRD вместо таблиц, колонок и полей вводятся другие понятия. В ней есть так называемые источники данных (DS), которые сами по себе ничего не хранят. Для простоты их можно интерпретировать как обычные колонки в таблице. Хранение же данных возлагается на кольцевые архивы (RRA). RRA привязывается к источнику данных и обладает такими свойствами как: количество ячеек; применяемая функция консолидации; интервал времени, после которого к данным применяется функция консолидации, и результат ее работы записывается в очередную ячейку. Пожалуй, это все, что требуется знать о структуре данных в RRD.Установка
На момент написания статьи в портах доступна версия 1.4.5. Итак, идем порты и ставим (обратите внимание на то, что в портах есть несколько версий данного пакета):- # cd /usr/ports/databases/rrdtool
- # make install clean
- # ls /root/rrd
- cpu
- mem
- temp
- # ls -l /root/rrd/mem
- -rwxr-x--- 1 root wheel 1204 24 апр 12:36 create.sh
- -rwxr-x--- 1 root wheel 1827 24 апр 12:49 graph.sh
- -rw-r----- 1 root wheel 23976200 24 апр 21:15 mem.rrd
- -rwxr-x--- 1 root wheel 915 24 апр 00:18 update.sh
Интерфейс командной строки
С пакетом rrdtool ставится несколько утилит и одна из них имеет одноименное название - rrdtool. С помощью нее можно осуществлять различные манипуляции с кольцевой базой данных (создавать/изменять БД, обновлять/извлекать данные, строить графики и т.п.). Утилита имеет следующий синтаксис:- rrdtool [options] command command_options
- Создание кольцевой базы данных
Описание параметров:
- rrdtool create filename [--start|-b start time]
- [--step|-s step]
- [--no-overwrite|-O]
- [DS:ds-name:DST:dst arguments]
- [RRA:CF:cf arguments]
- filename - имя файла.
- --start, -b - время в секундах, прошедших с начала эпохи Unix (1970-01-01 UTC), с которого происходит сбор статистики. RRDtool не будет принимать данные старее указанного здесь времени. По умолчанию: now - 10 секунд.
- --step, -s - интервал, через который данные поступают в базу. По умолчанию: 300 секунд.
- --no-overwrite, -O - не перезаписывать существующий файл с таким же именем.
- DS:ds-name:DST:dst arguments - источник данных или проще - колонка в БД, в которой хранятся данные.
- ds-name - имя колонки (не может быть длиннее 19 символов; допустимые символы: [a-zA-Z0-9_]).
- DST - тип источника данных. Может принимать значения:
- GAUGE - подходит для данных типа: температуры, загрузки процессора, объема памяти.
- COUNTER - предназначен для хранения данных с счетчиков, например трафика. Подразумевается, что значение счетчика никогда не уменьшается, за исключением случая его переполнения.
- DERIVE - счетчик, который может уменьшаться.
- ABSOLUTE - тоже счетчик, только он сбрасывается после чтения.
- COMPUTE - позволяет задать rpn-формулу для обработки данных.
- heartbeat - максимальное кол-во секунд ожидания данных для ячейки, после которого значение помечается как UNKNOWN. Рекомендуется устанавливать в 2*step.
- min - минимально допустимое значение. Если ограничений нет, то указывайте здесь U.
- max - максимально допустимое значение. Если ограничений нет, то указывайте здесь U.
- RRA:CF:xff:steps:rows - параметры кольцевых архивов (RRA). Каждый такой архив может содержать некоторые значения или статистику для DS за определенный период. Прежде чем попасть в архив, данные обрабатываются функцией консолидации (CF). Доступны следующие функции консолидации:
- AVERAGE - среднее значение за определенный период
- MIN - минимальное значение
- MAX - максимальное значение
- LAST - последнее значение
- Занесение данных в базу
Описание параметров:
- rrdtool update filename
- [--template|-t ds-name:ds-name:...]
- [--daemon <address>]
- time|N:value[:value...]
- at-time@value[:value...]
- [ time:value[:value...] ..]
- filename - имя файла.
- --template, -t - с помощью этой опции задается шаблон, который позволяет вам указать в какие источники данных и в каком порядке необходимо произвести запись в базу. Если указанных здесь источников данных нет в файле, то запись будет отменена и прога выкинет ошибку.
- --daemon - если задан, то rrdtool будет пытать подключиться к демону rrdcached. Если попытка будет неудачной, то выдается сообщение об ошибке.
- time|N:value[:value...] - данные, связанные со временем, которые пишутся в базу. Если во времени указать N, то будет подставлено текущее время. Время так же можно задавать в секундах с начала эпохи Unix или в стиле AT (за подробностями в документацию).
- Получение данных из базы
Описание параметров:
- rrdtool fetch filename.rrd CF
- [-r|--resolution resolution]
- [-s|--start start] [-e|--end end]
- [--daemon <address>]
- filename - имя файла.
- CF - функция консолидации применяемая к данным, которые вы хотите получить.
- -r, --resolution - требуемый интервал значений.
- -s, --start - время, с которого выводить данные. По умолчанию: end-1day.
- -e, --end - время, до которого выводить данные. По умолчанию: now.
- --daemon - адрес демона rrdcached.
- Получение информации о структуре базы данных в удобном формате
- rrdtool info filename.rrd
- Изменение размера RRA
- rrdtool resize filename rranum GROW|SHRINK rows
- filename - имя файла.
- rranum - номер RRA. Номер можно узнать с помощью команды rrdtool info.
- GROW|SHRINK - действие к RRA: увеличить/уменьшить.
- rows - количество добавляемых/удаляемых ячеек.
- Изменение некоторых характеристик базы данных
С помощью данной команды можно изменить характеристики базы или отдельно взятого DS (например, переименовать его). За информацией обращайтесь в документацию.
- rrdtool tune filename [options]
- Рисование графиков
Вот описание некоторых опций (за полным списком обращайтесь в документацию):
- rrdtool graph filename [options]
- filename - имя графического файла.
- -s, --start seconds - время, с которого начать строить график. По умолчанию: end - 1 день.
- -e, --end seconds - время, до которого строить график. По умолчанию: now.
- -o, --logarithmic - логарифмическое масштабирование оси ординат.
- -z, --lazy - генерировать новый графический файл, если предыдущий устарел или его не существует.
- -g, --no-legend - не выводить описания графиков.
- --legend-position=(north|south|west|east) - позиция для вывода описания графиков. По умолчанию: south.
- --legend-direction=(topdown|bottomup) - выводить описание графиков по вертикали, с указанным здесь направлением.
- --daemon - адрес демона rrdcached.
- -j, --only-graph - вывести только график, без какого-либо текста.
- -T, --tabwidth width - ширина табуляции в пикселях. По умолчанию: 40.
- -E, --slope-mode - может немного улучшить внешний вид картинки.
- -a, --imgformat PNG|SVG|EPS|PDF - формат графического файла.
- -t, --title string - заголовок, помещаемый вверху графика.
- -v, --vertical-label - вертикальный текст, слева от графика.
- -w, --width - длина картинки в пикселях. По умолчанию: 400.
- -h, --height - высота картинки в пикселях. По умолчанию: 100.
- DEF:vname=rrd:ds-name:CF - данный параметр позволяет выдернуть данные из определенного источника данных (а точнее из кольцевого архива, связанного с ним) в базе и использоваит эти данные для построения графика.
- vname=rrd - vname - имя переменной, через которую можно обращаться к данным, а rrd - путь до базы данных.
- ds-name - имя источника данных в БД.
- CF - функция консолидации, чтобы тулза знала из какого RRA выдергивать данные.
- CDEF:vname=rpn-expression - позволяет задать новую переменную, которая будет содержать результат математического выражения, записанного в обратной польской нотации.
- VDEF:vdefname=rpn-expression - позволяет задать переменную, которая будет содержать результат применяемой функции к данным. Функции могут быть такими: AVERAGE, MAXIMUM, MINIMUM, LAST.
- PRINT:vdefname:format - выводит строку в раздел описания графика(ов). Как правильно оформить поле format смотрите в документации.
- GPRINT:vdefname:format - работает так же, как и PRINT.
- COMMENT:text - выводит обычный текст.
- TEXTALIGN:{left|right|justified|center} - выравнивание текста в разделе описания графиков.
- LINE[width]:vname[#rrggbb[aa][:[legend][:STACK]]] - рисует линию графика, определенной толщины (width) и для определенной переменной (vname). Можно задать цвет и описание (которое будет выводится в разделе описания графиков). Ключевое слово STACK значит, что данная линия будет рисоваться над предыдущей LINE или AREA.
- AREA:vname[#rrggbb[aa][:[legend][:STACK]]] - данная опция аналогична LINE, только все параметры задаются для внутренней области графика (то есть для того, что под LINE)
Мониторинг загрузки процессора
Вот и настало время для первого практического примера )). Перед созданием БД сначала необходимо продумать какие данные будут храниться в ней. В большинстве Unix-подобных систем процессор может находиться в 5 состояниях (user, system, nice, intr, idle) и FreeBSD не исключение. Я хочу хранить каждое состояние отдельно, а если необходимо будет что-нибудь объединить, то простыми арифметическими действиями эту задачу очень просто решить. Итак, нам необходима база данных с 5 DS (источниками данных). Теперь нужно решить какие RRA понадобятся и за какой интервал времени одна ячейка будет хранить данные (чем меньше интервал, тем точнее будет график). Для построения более точного графика данные будут сниматься каждую минуту и будет несколько RRA (забыл сказать - данные будут храниться за год):- Каждая ячейка хранит данные за каждый отсчет (то есть запись идет каждые 60 секунд). Чтобы хранить столько данных понадобится 365*24*60*60/60=525600 ячеек.
- Каждая ячейка хранит данные за 15 минут (то есть данные будут накапливаться в течении 15 минут, далее к ним применяется функция консолидации и только тогда происходит запись). Чтобы хранить столько данных понадобится 365*24*60*60/(60*15)=35040 ячеек.
- Каждая ячейка хранит данные за 30 минут. Чтобы хранить столько данных понадобится 365*24*60*60/(60*30)=17520 ячеек.
- Каждая ячейка хранит данные за 60 минут. Чтобы хранить столько данных понадобится 365*24*60*60/(60*60)=8760 ячеек.
P.S. На данный момент я использую только 1 RRA, остальные сделал на всякий случай, вдруг понадобятся.Так же будут RRA с разными функциями консолидации, поэтому придется продублировать RRA для каждого интервала времени. Чтобы не набивать каждый раз все руками (а набивать много), лучше сразу писать скрипт. Вот так выглядит скрипт для создания требуемой БД:
- # cat /root/rrd/cpu/create.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/cpu/cpu.rrd"
- # ds0 - user
- # ds1 - nice
- # ds2 - system
- # ds3 - intr
- # ds4 - idle
- # Статистика хранится за год
- # А так же хранится среднее за 15,30,60 минут
- rrdtool create $RRD_BASE --step 60 \
- DS:ds0:GAUGE:120:0:100 \
- DS:ds1:GAUGE:120:0:100 \
- DS:ds2:GAUGE:120:0:100 \
- DS:ds3:GAUGE:120:0:100 \
- DS:ds4:GAUGE:120:0:100 \
- RRA:AVERAGE:0.5:1:525600 \
- RRA:AVERAGE:0.5:15:35040 \
- RRA:AVERAGE:0.5:30:17520 \
- RRA:AVERAGE:0.5:60:8760 \
- RRA:MIN:0.5:1:525600 \
- RRA:MIN:0.5:15:35040 \
- RRA:MIN:0.5:30:17520 \
- RRA:MIN:0.5:60:8760 \
- RRA:MAX:0.5:1:525600 \
- RRA:MAX:0.5:15:35040 \
- RRA:MAX:0.5:30:17520 \
- RRA:MAX:0.5:60:8760
- exit 0
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/param.h>
- #include <sys/resource.h>
- #include <sys/sysctl.h>
- #include <kvm.h>
- #include <fcntl.h>
- static struct {
- const char *name;
- } cpu_states[CPUSTATES] = {
- "user", "nice", "system", "intr", "idle"
- };
- static void error_log(const char *msg);
- int main()
- {
- int i;
- kvm_t *km = NULL;
- long cpu_load[CPUSTATES];
- long cpu_load2[CPUSTATES];
- long long total;
- km = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
- if (km == NULL) error_log("kvm_open");
- if (kvm_getcptime(km, cpu_load) == -1){
- kvm_close(km);
- error_log("kvm_getcptime");
- }
- usleep(1000000);
- if (kvm_getcptime(km, cpu_load2) == -1){
- kvm_close(km);
- error_log("kvm_getcptime");
- }
- kvm_close(km);
- total = 0;
- for (i = 0; i < CPUSTATES; i++)
- total += cpu_load2[i] - cpu_load[i];
- for (i = 0; i < CPUSTATES; i++)
- for (i = 0; i < CPUSTATES; i++)
- return 0;
- }
- static void error_log(const char *msg)
- {
- }
- gcc -o cpuload main.c -lkvm
- # cat /root/rrd/cpu/update.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/cpu/cpu.rrd"
- str=`/root/rrd/cpu/cpuload | tail +2`
- cpu_user=`echo $str | awk '{ print $1; }'`
- cpu_nice=`echo $str | awk '{ print $2; }'`
- cpu_sys=`echo $str | awk '{ print $3; }'`
- cpu_intr=`echo $str | awk '{ print $4; }'`
- cpu_idle=`echo $str | awk '{ print $5; }'`
- rrdtool update $RRD_BASE N:$cpu_user:$cpu_nice:$cpu_sys:$cpu_intr:$cpu_idle
- exit 0
- # cat /root/rrd/cpu/graph.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/cpu/cpu.rrd"
- DAYS="6h 1d 7d 30d 1y"
- DATE="`date '+%d-%m-%Y %H\:%M\:%S'`"
- for day in $DAYS; do
- rrdtool graph "/home/user/data/www/info-x.org/stats/cpu_${day}.png" \
- --start end-${day} --slope-mode \
- --title "Статистика использования процессора" \
- --width 500 --height 200 \
- --imgformat PNG \
- DEF:cpu_user=$RRD_BASE:ds0:AVERAGE:step=1 \
- DEF:cpu_nice=$RRD_BASE:ds1:AVERAGE:step=1 \
- DEF:cpu_sys=$RRD_BASE:ds2:AVERAGE:step=1 \
- DEF:cu_max=$RRD_BASE:ds0:MAX:step=1 \
- DEF:cu_min=$RRD_BASE:ds0:MAX:step=1 \
- DEF:cn_max=$RRD_BASE:ds1:MAX:step=1 \
- DEF:cn_min=$RRD_BASE:ds1:MAX:step=1 \
- DEF:cs_max=$RRD_BASE:ds2:MAX:step=1 \
- DEF:cs_min=$RRD_BASE:ds2:MAX:step=1 \
- TEXTALIGN:left \
- COMMENT:" " \
- COMMENT:"Максимальная " \
- COMMENT:"Минимальная " \
- COMMENT:"Средняя\l" \
- LINE2:cpu_user#FF3333:"Процессы пользователей\:" \
- GPRINT:cu_max:MAX:"%22.2lf%%" \
- GPRINT:cu_min:MIN:"%12.2lf%%" \
- GPRINT:cpu_user:AVERAGE:"%8.2lf%%\l" \
- AREA:cpu_user#FF6666 \
- LINE2:cpu_sys#3366FF:"Процессы ядра\:" \
- GPRINT:cs_max:MAX:"%31.2lf%%" \
- GPRINT:cs_min:MIN:"%12.2lf%%" \
- GPRINT:cpu_sys:AVERAGE:"%8.2lf%%\l" \
- AREA:cpu_sys#6699FF \
- LINE1:cpu_nice#48D1CC:"Процессы с измененным приоритетом\:" \
- GPRINT:cn_max:MAX:"%11.2lf%%" \
- GPRINT:cn_min:MIN:"%12.2lf%%" \
- GPRINT:cpu_nice:AVERAGE:"%8.2lf%%\l" \
- COMMENT:"\s" \
- COMMENT:"\s" \
- COMMENT:"Последнее обновление\: $DATE\r" \
- > /dev/null 2>&1
- done
- exit 0
- SHELL=/bin/sh
- PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
- #min hour day month day of week command
- */1 * * * * /root/rrd/cpu/update.sh
- 0 */6 * * * /root/rrd/cpu/graph.sh
Мониторинг температуры процессора
Температуру процессора можно снять несколькими способами. Если у вас материнская плата от ASUS, то можно загрузить модуль acpi_aiboost.ko, который позволит получить доступ к сенсорам материнской платы. Можно пойти другим путем - в современных процессорах есть собственные датчики температуры, доступ к ним можно получить, загрузив модуль amdtemp.ko для AMD или coretemp.ko для Intel. Доступ к данным можно получить через системное дерево MIB (sysctl). У меня стоит проц от AMD, поэтому я подгрузил соответствующий модуль для данного процессора, который в MIB добавил следующие элементы:- dev.amdtemp.0.sensor0.core0
- dev.amdtemp.0.sensor0.core1
- dev.amdtemp.0.sensor1.core0
- dev.amdtemp.0.sensor1.core1
- # cat /root/rrd/temp/create.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/temp/temp.rrd"
- # Статистика хранится за месяц
- # ds0 - sensor 0, core 0
- # ds1 - sensor 0, core 1
- # ds2 - sensor 1, core 0
- # ds3 - sensor 1, core 1
- # Усредненные значения за 15,30,60 минут
- rrdtool create $RRD_BASE --step 300 \
- DS:ds0:GAUGE:600:U:U \
- DS:ds1:GAUGE:600:U:U \
- DS:ds2:GAUGE:600:U:U \
- DS:ds3:GAUGE:600:U:U \
- RRA:AVERAGE:0.5:1:8640 \
- RRA:AVERAGE:0.5:3:2880 \
- RRA:AVERAGE:0.5:6:1440 \
- RRA:AVERAGE:0.5:12:720 \
- RRA:MIN:0.5:1:8640 \
- RRA:MIN:0.5:3:2880 \
- RRA:MIN:0.5:6:1440 \
- RRA:MIN:0.5:12:720 \
- RRA:MAX:0.5:1:8640 \
- RRA:MAX:0.5:3:2880 \
- RRA:MAX:0.5:6:1440 \
- RRA:MAX:0.5:12:720
- exit 0
- # cat /root/rrd/temp/update.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/temp/temp.rrd"
- # dev.amdtemp.0.sensor0.core0
- # dev.amdtemp.0.sensor0.core1
- # dev.amdtemp.0.sensor1.core0
- # dev.amdtemp.0.sensor1.core1
- sc00=`sysctl -n dev.amdtemp.0.sensor0.core0 | awk '{ print substr($1, 1, index($1, "C")-1); }' | sed 's/,/\./'`
- sc01=`sysctl -n dev.amdtemp.0.sensor0.core1 | awk '{ print substr($1, 1, index($1, "C")-1); }' | sed 's/,/\./'`
- sc10=`sysctl -n dev.amdtemp.0.sensor1.core0 | awk '{ print substr($1, 1, index($1, "C")-1); }' | sed 's/,/\./'`
- sc11=`sysctl -n dev.amdtemp.0.sensor1.core1 | awk '{ print substr($1, 1, index($1, "C")-1); }' | sed 's/,/\./'`
- rrdtool update $RRD_BASE N:$sc00:$sc01:$sc10:$sc11
- exit 0
- # cat /root/rrd/temp/graph.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/temp/temp.rrd"
- DAYS="1d"
- DATE="`date '+%d-%m-%Y %H\:%M\:%S'`"
- for day in $DAYS; do
- rrdtool graph "/home/user/data/www/info-x.org/stats/temp_${day}.png" \
- --start end-${day} --slope-mode \
- --title "CPU temperature (C)" \
- --width 500 --height 200 \
- --imgformat PNG \
- DEF:sc00=$RRD_BASE:ds0:AVERAGE:step=1 \
- DEF:sc01=$RRD_BASE:ds1:AVERAGE:step=1 \
- DEF:sc10=$RRD_BASE:ds2:AVERAGE:step=1 \
- DEF:sc11=$RRD_BASE:ds3:AVERAGE:step=1 \
- DEF:sc00_max=$RRD_BASE:ds0:MAX:step=1 \
- DEF:sc01_max=$RRD_BASE:ds1:MAX:step=1 \
- DEF:sc10_max=$RRD_BASE:ds2:MAX:step=1 \
- DEF:sc11_max=$RRD_BASE:ds3:MAX:step=1 \
- DEF:sc00_min=$RRD_BASE:ds0:MIN:step=1 \
- DEF:sc01_min=$RRD_BASE:ds1:MIN:step=1 \
- DEF:sc10_min=$RRD_BASE:ds2:MIN:step=1 \
- DEF:sc11_min=$RRD_BASE:ds3:MIN:step=1 \
- TEXTALIGN:center \
- LINE1:sc00#00FF00:"Core 0 Sensor 0\t" \
- GPRINT:sc00_max:MAX:"Max\: %1.0lf\t" \
- GPRINT:sc00_min:MIN:"Min\: %1.0lf\t" \
- GPRINT:sc00:AVERAGE:"Avg\: %1.0lf\l" \
- LINE1:sc01#0000FF:"Core 0 Sensor 1\t" \
- GPRINT:sc01_max:MAX:"Max\: %1.0lf\t" \
- GPRINT:sc01_min:MIN:"Min\: %1.0lf\t" \
- GPRINT:sc01:AVERAGE:"Avg\: %1.0lf\l" \
- LINE1:sc10#FF0000:"Core 1 Sensor 0\t" \
- GPRINT:sc10_max:MAX:"Max\: %1.0lf\t" \
- GPRINT:sc10_min:MIN:"Min\: %1.0lf\t" \
- GPRINT:sc10:AVERAGE:"Avg\: %1.0lf\l" \
- LINE1:sc11#000000:"Core 1 Sensor 1\t" \
- GPRINT:sc11_max:MAX:"Max\: %1.0lf\t" \
- GPRINT:sc11_min:MIN:"Min\: %1.0lf\t" \
- GPRINT:sc11:AVERAGE:"Avg\: %1.0lf\l" \
- COMMENT:"\r" \
- COMMENT:"Last updated\: $DATE\l" \
- > /dev/null 2>&1
- done
- exit 0
- */5 * * * * /root/rrd/temp/update.sh
- 0 */6 * * * /root/rrd/temp/graph.sh
Мониторинг использования памяти
Для мониторинга памяти проще всего использовать данные из системного дерева MIB. В MIB можно найти данные о свободных/используемых страницах памяти. Если взять эти значения и умножить на размер страницы, то мы получим объем памяти в байтах. Для определения объема свободного/занятого свопа я распарсил вывод команды swapinfo.- vm.stats.vm.v_page_size - размер страницы в байтах
- vm.stats.vm.v_free_count - объем свободной памяти в страницах
- vm.stats.vm.v_inactive_count - объем неактивной памяти в страницах
- vm.stats.vm.v_active_count - объем активной памяти в страницах
- vm.stats.vm.v_wire_count - объем связанной памяти в страницах
- vm.stats.vm.v_cache_count - объем кэшированной памяти в страницах
- # cat /root/rrd/mem/create.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/mem/mem.rrd"
- # Статистика хранится за месяц
- # ds0 - свободная память
- # ds1 - неактивная память
- # ds2 - активная память
- # ds3 - wired память
- # ds4 - кэшированая память
- # ds5 - использование свопа
- # Усредненные значения за 15,30,60 минут
- rrdtool create $RRD_BASE --step 300 \
- DS:ds0:GAUGE:600:U:U \
- DS:ds1:GAUGE:600:U:U \
- DS:ds2:GAUGE:600:U:U \
- DS:ds3:GAUGE:600:U:U \
- DS:ds4:GAUGE:600:U:U \
- DS:ds5:GAUGE:600:U:U \
- RRA:AVERAGE:0.5:1:105120 \
- RRA:AVERAGE:0.5:3:35040 \
- RRA:AVERAGE:0.5:6:17520 \
- RRA:AVERAGE:0.5:12:8760 \
- RRA:MIN:0.5:1:105120 \
- RRA:MIN:0.5:3:35040 \
- RRA:MIN:0.5:6:17520 \
- RRA:MIN:0.5:12:8760 \
- RRA:MAX:0.5:1:105120 \
- RRA:MAX:0.5:3:35040 \
- RRA:MAX:0.5:6:17520 \
- RRA:MAX:0.5:12:8760
- exit 0
- # cat /root/rrd/mem/update.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/mem/mem.rrd"
- page_size=`sysctl -n vm.stats.vm.v_page_size`
- mem_free=`sysctl -n vm.stats.vm.v_free_count`
- mem_inact=`sysctl -n vm.stats.vm.v_inactive_count`
- mem_use=`sysctl -n vm.stats.vm.v_active_count`
- mem_wired=`sysctl -n vm.stats.vm.v_wire_count`
- mem_cached=`sysctl -n vm.stats.vm.v_cache_count`
- swap_use=`swapinfo | tail +2 | awk '{ print $3; }'`
- mem_free=$(($mem_free * $page_size))
- mem_inact=$(($mem_inact * $page_size))
- mem_use=$(($mem_use * $page_size))
- mem_wired=$(($mem_wired * $page_size))
- mem_cached=$(($mem_cached * $page_size))
- rrdtool update $RRD_BASE N:$mem_free:$mem_inact:$mem_use:$mem_wired:$mem_cached:$swap_use
- exit 0
- # cat /root/rrd/mem/graph.sh
- #!/bin/sh
- RRD_BASE="/root/rrd/mem/mem.rrd"
- DAYS="1d 7d 30d 1y"
- DATE="`date '+%d-%m-%Y %H\:%M\:%S'`"
- for day in $DAYS; do
- rrdtool graph "/home/user/data/www/info-x.org/stats/mem_${day}.png" \
- --start end-${day} --slope-mode --base 1024 \
- --title "Статистика использования памяти" \
- --width 500 --height 200 \
- --imgformat PNG \
- DEF:mem_free=$RRD_BASE:ds0:AVERAGE:step=1 \
- DEF:mem_inact=$RRD_BASE:ds1:AVERAGE:step=1 \
- DEF:mem_use=$RRD_BASE:ds2:AVERAGE:step=1 \
- DEF:mem_wired=$RRD_BASE:ds3:AVERAGE:step=1 \
- DEF:mem_cached=$RRD_BASE:ds4:AVERAGE:step=1 \
- DEF:swap_use=$RRD_BASE:ds5:AVERAGE:step=1 \
- CDEF:mem_free_mb=mem_free,1048576,/ \
- CDEF:mem_inact_mb=mem_inact,1048576,/ \
- CDEF:total_use=mem_use,mem_wired,+ \
- CDEF:total_use_mb=total_use,1048576,/ \
- CDEF:mem_cached_mb=mem_cached,1048576,/ \
- CDEF:su_mb=swap_use,1024,/ \
- VDEF:mem_free_max=mem_free_mb,MAXIMUM \
- VDEF:mem_free_min=mem_free_mb,MINIMUM \
- VDEF:mem_inact_max=mem_inact_mb,MAXIMUM \
- VDEF:mem_inact_min=mem_inact_mb,MINIMUM \
- VDEF:tu_max=total_use_mb,MAXIMUM \
- VDEF:tu_min=total_use_mb,MINIMUM \
- VDEF:mem_cached_max=mem_cached_mb,MAXIMUM \
- VDEF:mem_cached_min=mem_cached_mb,MINIMUM \
- VDEF:su_max_mb=su_mb,MAXIMUM \
- VDEF:su_min_mb=su_mb,MINIMUM \
- TEXTALIGN:center \
- LINE2:total_use#00FF00:"Используемая память (active + wired)\l" \
- AREA:total_use#00CC00 \
- LINE1:swap_use#0000FF:"Использование раздела подкачки\l" \
- AREA:swap_use#0000CC \
- LINE1:mem_free#FF0000:"Свободная память (free)\l" \
- LINE1:mem_inact#FFCC00:"Неактивная память (inactive)\l" \
- LINE1:mem_cached#FF00CC:"Кешированная память (cache)" \
- COMMENT:"\n" \
- COMMENT:" \n" \
- COMMENT:" " \
- COMMENT:"Максимум " \
- COMMENT:"Минимум " \
- COMMENT:"В среднем\l" \
- COMMENT:"Используемая\:" \
- GPRINT:tu_max:"%10.0lf Мб" \
- GPRINT:tu_min:"%14.0lf Мб" \
- GPRINT:total_use_mb:AVERAGE:"%16.0lf Мб\l" \
- COMMENT:"Подкачка\:" \
- GPRINT:su_max_mb:"%14.0lf Мб" \
- GPRINT:su_min_mb:"%14.0lf Мб" \
- GPRINT:su_mb:AVERAGE:"%16.0lf Мб\l" \
- COMMENT:"Свободная\:" \
- GPRINT:mem_free_max:"%13.0lf Мб" \
- GPRINT:mem_free_min:"%14.0lf Мб" \
- GPRINT:mem_free_mb:AVERAGE:"%16.0lf Мб\l" \
- COMMENT:"Неактивная\:" \
- GPRINT:mem_inact_max:"%12.0lf Мб" \
- GPRINT:mem_inact_min:"%14.0lf Мб" \
- GPRINT:mem_inact_mb:AVERAGE:"%16.0lf Мб\l" \
- COMMENT:"Кешированная\:" \
- GPRINT:mem_cached_max:"%10.0lf Мб" \
- GPRINT:mem_cached_min:"%14.0lf Мб" \
- GPRINT:mem_cached_mb:AVERAGE:"%16.0lf Мб\l" \
- COMMENT:"\r" \
- COMMENT:"Последнее обновление\: $DATE\r" \
- > /dev/null 2>&1
- done
- exit 0
- */5 * * * * /root/rrd/mem/update.sh
- 0 */6 * * * /root/rrd/mem/graph.sh
Заключение
Надеюсь, в этой статье мне удалось достаточно подробно рассказать о том, как можно использовать RRDtool для мониторинга системы. Правда такой метод подходит, когда нужно мониторить всего одну или две машины. Для отслеживания работы парка машин лучше использовать специально разработанные программные комплексы (например, Cacti, Nagios, Zabbix и т.п.). Так же стоит отметить, что некоторые программы для мониторинга системы (например, Cacti) используют RDDtool для хранения данных и построения графиков на основе этих данных. Такие программы просто используют готовые шаблоны для визуализации данных, и в таком случае данная статья будет полезна, так как знать принцип работы RRDtool не помешает.Полезные ссылки
Обсуждение статьи
чт, 11/07/2019 - 22:24
чт, 11/07/2019 - 13:47
Нужна помощь в разборе параметров строки CDEF.