trafd count.pl - обновлённый скрипт

Материал из Lblss.ru
Перейти к: навигация, поиск

Версия скрипта снятия трафика с trafd, тупо переписанная на PERL - для учета интернет-трафика. Преимущество перед shell-версией: работает на одном коннекте к базе, потому процесс записи происходит в разы быстрее.

Софт

Кроме Perl (который установлен по дефолту) для работы скрипта необходимо установить:

  • p5-DBI - /usr/ports/databases/p5-DBI (интерфейс)
  • p5-DBD-mysql51-4.005 - /usr/ports/databases/p5-DBD-mysql51 (драйвер)

Строка запуска

*/5 * * * * /root/trafd_count.pl 1>/tmp/trafd_count 2>&1

Код

#!/usr/bin/perl -W
 
use DBI;
# Адрес MySQL сервера
$MySQL_host="sqlserver.local"; # или тупо по айпи $MySQL_host="192.168.0.254";
# Имя пользователя для доступа к БД в которой храниться траффик
$user_name="trafdusr";
# Пароль пользователя MySQL
$user_passw="trafdpassword";
# Имя базы данных
$db_name="trafd";
 
# коннект
unless($dbh = DBI->connect("DBI:mysql:$db_name:$MySQL_host",$user_name,$user_passw)) {
  die("Cannot connect to SQL-server.");
}
 
# текущие дата-время
use Time::localtime;
$tm = localtime;
# Сегодяшний день, месяц, год
($day, $month, $year) = ($tm->mday, sprintf("%02d", $tm->mon+1), $tm->year+1900);
$curr_date = $year . "-" . $month . "-" . $day;
# Текущее время (секунды специально сделаны 00 - иногда cron запускает скрипт не
# в 00 секунд а позже).
$curr_time = $tm->hour . ":" . $tm->min . ":00";
 
# создаем временную таблицу для промежуточной обработки
$dbh->do("
CREATE TABLE IF NOT EXISTS `traffic_tmp` (
    `date` DATE NOT NULL,
    `time` TIME NOT NULL,
    `from_IP` CHAR(16) NOT NULL,
    `port_from_IP` CHAR(8) NOT NULL,
    `to_IP` CHAR(16) NOT NULL,
    `port_to_IP` CHAR(8) NOT NULL,
    `protocol` ENUM('icmp','tcp','udp') NOT NULL,
    `bytes` int(16) NOT NULL,
    `all_bytes` int(16) NOT NULL
) TYPE=MyISAM COMMENT='tmp_table'");
 
# Директория в которой будут храниться текстовые файлы с логами trafd
$NewDir="/var/traffic/$year/$month";
# Пытаемся создать эту самую директорию на случай если это первый запуск
# или произошла смена месяца (года)
`mkdir -p $NewDir`;
# Считываем строку из файла /etc/rc.conf с целью извлечь оттуда
# названия интерфейсов по которым работает trafd
$ifs = `. /etc/rc.conf ; echo \$trafd_ifaces`;
 
# теперь по интерфейсам в цикле
foreach $iface(split(' ', $ifs)) {
    # Сохраняем статистику по текущему интерфейсу
    `/usr/local/bin/trafsave $iface`;
    # Преобразуем логи из двоичного в текстовый формат. Сохраняются они в
    # папке /tmp в виде файлов summary.* c расширением по имени интерфейса
    `/usr/local/bin/traflog -i $iface -a -n -s > /tmp/summary.$iface 2>/dev/null`;
    # Очищаем файл с логами в двоичном формате
    `cat /dev/null > /usr/local/var/trafd/trafd.$iface`;
    # Дозаписываем логи в текстовый файл (пусть лежат на всякий случай...)
    `cat /tmp/summary.$iface >> $NewDir/summary.$iface`;
    # очищаем временную таблицу
    $dbh->do("TRUNCATE TABLE `traffic_tmp`;");
 
    # открываем временный файл логов для чтения
    open(TLOG,"</tmp/summary.${iface}");
    @strs = <TLOG>;
    close(TLOG);
 
    foreach $str(@strs) {
        @args = split(/[\s]+/, $str);
        # Загоняем полученную строку во временную таблицу
        $dbh->do("
            INSERT INTO `traffic_tmp` (
                `date`, `time`,
                `from_IP`, `port_from_IP`,
                `to_IP`, `port_to_IP`,
                `protocol`, `bytes`,
                `all_bytes`
            )
            values (
                '${curr_date}', '${curr_time}',
                '$args[0]', '$args[1]',
                '$args[2]', '$args[3]',
                '$args[4]', '$args[5]',
                '$args[6]'
            );");
    }
 
    # Стираем пустые строки, с нулем байт и технической инфой
    $dbh->do("
        DELETE FROM 
          `traffic_tmp`
        WHERE 
          (`from_IP`='' AND `port_from_IP`='' AND `to_IP`='' AND `port_to_IP`='' AND `protocol`='')
          OR `all_bytes`='0' OR `from_IP`='';");
 
    # Создаём таблицу для окончательного хранения траффика
    $dbh->do("
        CREATE TABLE IF NOT EXISTS `${iface}_${year}-${month}` (
            `unic_id` INT(16) NOT NULL AUTO_INCREMENT,
            `date` DATE NOT NULL,
            `time` TIME NOT NULL,
            `from_IP` CHAR(16) NOT NULL,
            `port_from_IP` CHAR(8) NOT NULL,
            `to_IP` CHAR(16) NOT NULL,
            `port_to_IP` CHAR(8) NOT NULL,
            `protocol` ENUM('icmp','tcp','udp') NOT NULL,
            `bytes` int(16) NOT NULL,
            `all_bytes` int(16) NOT NULL,
            PRIMARY KEY (`unic_id`),
            KEY `date`(`date`)
        ) TYPE=MyISAM COMMENT='${iface} ${year}-${month}';
    ");
print "\n-- do INSERT --\n";
    # Перекидываем траффик из временной таблицы в окончательную, при этом
    # объединяем строки в которых совпадает ВСЁ кроме числа байт.
    $dbh->do("
        INSERT INTO `${iface}_${year}-${month}` (
            `date`, `time`, `from_IP`, `port_from_IP`, `to_IP`,
            `port_to_IP`, `protocol`, `bytes`, `all_bytes`
        )
        SELECT
            `date`, `time`, `from_IP`, `port_from_IP`, `to_IP`,
            `port_to_IP`, `protocol`, SUM(`bytes`) as `bytes`,  SUM(`all_bytes`) as `all_bytes`
        FROM
            `traffic_tmp`
        GROUP BY
            `date`, `time`, `from_IP`, `port_from_IP`, `to_IP`, `port_to_IP`, `protocol`;");
}
 
# Очищаем файл c логами о том когда и по какому интерфейсу сохранялась статистика
`cat /dev/null > /var/log/traffic.log`;
 
# вроде усе
$dbh->disconnect;
Персональные инструменты