Обсуждение статьи тематического каталога: Сага о биллинге или считаем траффик на FreeBSD (ng_ipacct + perl+ MySQL) (freebsd isp billing traffic netgraph perl mysql)Ссылка на текст статьи: http://www.opennet.me/base/net/ng_billing_letter.txt.html
Статья отличная!! Большое спасибо автору за его труд!
Прекрасная статья!
Вот только маленький впрос: где взять ng_ipacct для FreeBSD-5.4?
Здесь
ftp://ftp.wuppy.net.ru/pub/FreeBSD/local/kernel/ng_ipacct/
я ее не увидел. :-(
Предыдущая проблема решена. Возникла следующая:Имеется FreeBSD-5.4 и ng_ipacct для 5.x.
NETGRAPH вкомпилен в ядро "по-полной".
При запуске ng_ipacct:
==
kldload ng_ipacct > /dev/null 2>&1
ngctl mkpeer ${IFACE}: tee lower right
ngctl connect ${IFACE}: lower upper left
ngctl name ${IFACE}:lower ${IFACE}_acct_tee
/проходит нормально/
ngctl mkpeer ${IFACE}_acct_tee: ipacct right2left ${IFACE}_in
/задумывается и выбрасывает в перезагрузку/
==
Когда ядро было скомпилено только с netgraph, ng_ether, ng_socket и ng_tee, или с kldload их же, начиная с
ngctl connect ${IFACE}: lower upper left
сыплются ошибки File not foundnote: IFACE="rl0"
Подскажите, где грабли?
Спасибо!
я бы поставил за эту статью 3 с натяжкой(по 5 бальной шкале). В статье описывается тока принципы копирования и сохранения информации о трафике в базу. Но с таким форматом также не удобно работать. Статья нуждается в серъезной доработке.
Огромное спасибо автору. Я совсем ньюби во фре, но даже у меня за 4 дня всё получилось. ставил на фре 6.0 + mysql 5.15
Неплохо, но стиль программирования на перле... брр...Если писать свой разборщик конфигов, то и DBI пользоваться не надо - нужно самостоятельно писать коннект к базе. Опять же, varchar(255) для IP-адреса - почему так мало? А если адрес будет в 256 байт?
Писал подобное, только гораздо навароченнее.А)У MySQL есть отличный метод "LOAD DATA INFILE...." - закидываем в базу всё и оптом.
Б) 2Alex Povolotsky, где ты видел IP адрес длиннее хотя бы 255 байт? Автору, использование VARCHAR полей для src/dst port и т.п. - крайне не эффективно, достаточно 2х байтового unsingned целого. Со временем пришел и к тому, что src/dst ip пришлось хранить в unsigned int. а для поля bytes взял bigint. И хранится эффективнее (место), и ищется быстрее (операции над числами на порядок быстрее чем со строками), тем более и в php и средствами mysql можно легко переводить bin-ip в dot-string-ip.
p.s. Пока выложить сюда всё свое творение на основе этого не могу по финансовым соображения, чуть позже может выложу.
Спасибо автору - скрипты действительно удобнее оригинальных!однако тяжеловат стиль - я на перле каждый день програмлю и все равно мне сложно было прочитать весь объем.
ну и таки да - зачем строками хранить то что намного эффективнее хранить числами?
то есть кроме имени машины все остальное нужно держать в: unsigned int или bigint соответственно.2Alex Povolotsky - отдельное спасибо, насчет IP адреса длинее 255 байт я долго смеялся :))
поставил все работает, но ip_dest содержит внутренний ip роутера - где накосячил? Получается что все пакеты исходящие от роутера :(
FreeBSD 6.0 + Nat+IPFW+Squid.Подскажите плиз?
Отличная статья!
Большое спасибо!
> ip_from varchar(255)
> ip_to varchar(255)
аффтару низачот! научитесь считать до 15 (при IPv4) ну или до 45 (в случае IPv6), короче говоря стоит юзать varchar(15) для IPv4 или varchar(45) для IPv6... в общем статья неплохая, но как и было сказано - на троечку...
Посмотри для интереса еще мануал MySQL на тему функций INET_ATON() и INET_NTOA(), хранить ip в varchar'e не кошерно ;) Да и медленнее с varchar'ами опять же.
>Посмотри для интереса еще мануал MySQL на тему функций INET_ATON() и INET_NTOA(),
>хранить ip в varchar'e не кошерно ;) Да и медленнее с
>varchar'ами опять же.Посмотрите ниже на тему запостенного мною скрипта который эти ф-ции как раз и использует ;)
Вопрос аффтору.
Замем время и дату сначала загонять во временный файл, а потом его от туда вытаскивать для того, что-бы загнать в базу? Если можно просто загнать его в базу.
>Замем время и дату сначала загонять во временный файл, а потом его
>от туда вытаскивать для того, что-бы загнать в базу? Если можно
>просто загнать его в базу.Там применяется в корне неверная методика "INSERT INTO $table_date", в то время как правильнее было бы создать например CVS файл, а потом этот файл загнать в БД через LOAD DATA, т.к. это в разы быстрее чем INSERT-ом базу мучить...
Большая прозьба дать правельный метод. Очень надо.
>Большая прозьба дать правельный метод. Очень надо.например я вот так запихиваю статистику по netflow в БД:
собсно весь замут в том что flow-capture может передавать, при ротейте, имя файла некоему скрипту, который выглядит вот так:#!/bin/sh
# load MySQL configuration variables
if [ -r /usr/local/etc/mysql_clients.conf ]; then
. /usr/local/etc/mysql_clients.conf
fiprefix="/usr/local"
flow_export="$prefix/bin/flow-export"flow_dir="/usr/local/data/netflow/flows"
file_date="`date +%Y-%m-%d_%H-%M`"
flow_file_in="$1"
flow_file_out="$flow_dir/$file_date.csv"if [ -z $1 ]; then
echo "Usage: `basename $0` ft-xyz" >&2
exit 1
fiif [ -f $flow_file_in ]; then
$flow_export -f 2 -m UNIX_SECS,DFLOWS,DPKTS,DOCTETS,SRCADDR,DSTADDR,SRCPORT,DSTPORT,PROT,TOS < $flow_file_in > $flow_file_out
fiif [ -f $flow_file_out ]; then
$mysql -D netflow -B -e "LOAD DATA INFILE '$flow_file_out' INTO TABLE raw FIELDS TERMINATED BY ',' ENCLOSED BY '' LINES TERMINATED BY '\n'; DELETE FROM raw WHERE srcaddr='srcaddr' AND dstaddr='dstaddr'; INSERT INTO raw_data SELECT unix_secs,INET_ATON(srcaddr),INET_ATON(dstaddr),dpkts,doctets,srcport,dstport,prot,tos FROM raw; TRUNCATE TABLE raw;"
rm -f $flow_file_out
fiт.е. из бинарика flow-tools создается CVS файл который загружается в мускул, во временную БД через:
LOAD DATA INFILE '$flow_file_out' INTO TABLE raw FIELDS TERMINATED BY ',' ENCLOSED BY '' LINES TERMINATED BY '\n';
ну и потом разбирается и все... не скажу что супер-пупер метод, но... работает :)
Подскажите плиз...
как использовать функцию MySQL'я INET_ATON в данном скрипте (ng_stat_in.pl)? или это не реально? :(
=====
sub insert_data_db {
my ($dbh,$sth,$count);
$dbh = DBI->connect("DBI:mysql:host=$serverdb;database=$dbname","$dbuser","$dbpass")
or &error_connection_in;
$insert = "INSERT INTO $table_date (ip_from,s_port,ip_to,d_port,proto,packets,bytes,date_ins,time_ins,host,interface) VA
LUES (?,?,?,?,?,?,?,?,?,?,?)";$sth = $dbh->prepare("$insert");
#print "$insert\n";
while (@ipacct_arr_in) {
$line_in = shift @ipacct_arr_in;
($ip_from,$s_port,$ip_to,$d_port,$proto,$packets,$bytes,$date_ins,$time_ins,$host,$interface)=split(/[\s\t]+/,$l
ine_in);
if (!defined $proto){
$proto="0";
}
if (!defined $packets){
$packets="0";
}
if (!defined $bytes){
$bytes="0";
}
$sth->execute ($ip_from,$s_port,$ip_to,$d_port,$proto,$packets,$bytes,$date_ins,$time_ins,$host,$interface);
}$sth->finish;
$dbh->disconnect;
}
=====Спасибо
такая получилась проблема - есть пачка заархивированных логов за полгода.
надо их сунуть в мускуль.
по идее бы LOAD DATA INFILE использовать. Но тогда не получится заполнить поля date & time, которые беруться из названия обрабатываемого лога.
INSERT'ом сделать быстро не получилось.. за трое суток оно обработало два дня ) так нельзя..
Может есть у кого готовое решение?
>такая получилась проблема - есть пачка заархивированных логов за полгода.
>надо их сунуть в мускуль.
>по идее бы LOAD DATA INFILE использовать. Но тогда не получится заполнить
>поля date & time, которые беруться из названия обрабатываемого лога.
>INSERT'ом сделать быстро не получилось.. за трое суток оно обработало два дня
>) так нельзя..
>Может есть у кого готовое решение?
Терпение. И машину помошнее.
>такая получилась проблема - есть пачка заархивированных логов за полгода.
>надо их сунуть в мускуль.это проблема? ;)
>по идее бы LOAD DATA INFILE использовать. Но тогда не получится заполнить
>поля date & time, которые беруться из названия обрабатываемого лога.1. именно этот метод и надо использовать! ;)
2. кто Вам мешает не трогать поля времени и оставлять их оригинальными?
>за трое суток оно обработало два днячто-то Вы не то делаете... точно не то ;)
>Может есть у кого готовое решение?
на мой пост чуть выше гляньте - работает 100%, да, долго, но уж точо не за такое время как у Вас... у меня таким макаром месяц за пару часов вливается...
я может чего-то не понимаю но:
1. логи хранятся так /var/log/ipacct/2007-02-02/2007-02-02-10-fxp0.gz
2. в самих логах есть поля s_ip s_port d_ip d_port prot bytes in_out
3. в моей таблице ещё есть столбцы date и timeпри LOAD DATA INFILE я могу заполнить _только_ те поля, которые есть в загружаемом логе. Правильно ведь? Или я недостаточно хорошо читал описание для LOAD DATA INFILE?
У меня не получилось. В итоге конечно быстро все загружается. Но мои таблицы остаются с пустыми полями date & time и я не могу делать выборку по дням\часам. А надо. )Если парсить каждую строку и пихать инсертом - это висилица. Хотя может опять же что-то не так делаю? )
>я может чего-то не понимаю но:
>1. логи хранятся так /var/log/ipacct/2007-02-02/2007-02-02-10-fxp0.gz
>2. в самих логах есть поля s_ip s_port d_ip d_port prot bytes in_out
>3. в моей таблице ещё есть столбцы date и time
>
>при LOAD DATA INFILE я могу заполнить _только_ те поля, которые есть
>в загружаемом логе. Правильно ведь? Или я недостаточно хорошо читал описание
>для LOAD DATA INFILE?
>У меня не получилось. В итоге конечно быстро все загружается. Но мои
>таблицы остаются с пустыми полями date & time и я не
>могу делать выборку по дням\часам. А надо. )
>
>Если парсить каждую строку и пихать инсертом - это висилица. Хотя может
>опять же что-то не так делаю? )а если сделать вот так:
- загрузить данные за 1-й период
- потом простенько так:
UPDATE traffic SET traf_date_or_time = 'дата/время_файла' WHERE traf_date_or_time = '0000-00-00 00:00:00';
или
UPDATE traffic SET traf_date_or_time = 'дата/время_файла' WHERE traf_date_or_time = '';
или
UPDATE traffic SET traf_date_or_time = 'дата/время_файла' WHERE traf_date_or_time IS NULL;
или как нить еще, короче у вас после внесения в БД будет куча полей с данными о траффике но у них будет одно и то же время, которое указано через default при создании таблицы, а во время загрузки Вы (скрипт) точно знаете время к которому относится файл, верно? ну так ее (дату) и используете для установки времени данных
- повторяете для каждого файла
где-то примерно так ... по идее должно заработать ;)
>такая получилась проблема - есть пачка заархивированных логов за полгода.
>надо их сунуть в мускуль.
>по идее бы LOAD DATA INFILE использовать. Но тогда не получится заполнить
>поля date & time, которые беруться из названия обрабатываемого лога.
>INSERT'ом сделать быстро не получилось.. за трое суток оно обработало два дня
>) так нельзя..
>Может есть у кого готовое решение?http://dev.mysql.com/doc/refman/5.0/en/load-data.html
LOAD DATA INFILE 'file.txt'
INTO TABLE t1
(column1, column2)
SET column3 = CURRENT_TIMESTAMP;
Что мешает вставить вместо CURRENT_TIMESTAMP имя файла?
блин, точно.
мозг совсем работать перестал )
спасибо большое буду пробовать )
Помогите пожалуйста разобраться!
Собрал ядро 6.2:
options NETGRAPH
options NETGRAPH_ETHER
options NETGRAPH_SOCKET
options NETGRAPH_TEEВ ядре,а не в модуле, потому что нужно для других программ.
Обновил порты, поставил: ng_ipacct-20061223.tar.gz
Запускаю:
# ./ng_ipacct start
./ng_ipacct: DEBUG: checkyesno: ng_ipacct_enable is set to YES.
./ng_ipacct: DEBUG: run_rc_command: evaluating start_cmd().
./ng_ipacct: DEBUG: checkyesno: ng_ipacct_modules_load is set to NO.
./ng_ipacct: DEBUG: start ng_ipacct interface ng0
dlt = RAW
ngctl: send msg: Address already in use
ngctl: line 3: error in file
/usr/local/sbin/ipacctctl ng0_ip_acct:ng0 dlt RAW
/usr/local/sbin/ipacctctl ng0_ip_acct:ng0 threshold 5000
/usr/local/sbin/ipacctctl ng0_ip_acct:ng0 verbose 1
/usr/local/sbin/ipacctctl ng0_ip_acct:ng0 saveuid 0
/usr/local/sbin/ipacctctl ng0_ip_acct:ng0 savetime 0
# ngctl show ng0_ip_acct:
Name: ng0_ip_acct Type: ipacct ID: 0000000c Num hooks: 2
Local hook Peer name Peer type Peer ID Peer hook
---------- --------- --------- ------- ---------
ng0_out ks_ng0_out ksocket 0000000e inet/raw/divert
ng0_in ks_ng0_in ksocket 0000000d inet/raw/divert# ipacctctl ng0_ip_acct:ng0 checkpoint
# ipacctctl ng0_ip_acct:ng0 showПУСТОООО !!!!
Пробовал на разных интерфейсах: rl0, rl1, tun0
Ничего не выдаёт :(((
Помогите пожалуйста.
Или выдаёт такое:
# ipacctctl rl0_ip_acct:rl0 show
Accounting exceed threshold by 134 packets (10272 bytes)
Accounting exceed threshold by 22 packets (3357 bytes)А где обещанная детализация трафика ?
День добрый!При выполнении скрипта получаю ошибку:
# ./ng_stat_in.pl
install_driver(mysql) failed: Can't load '/usr/local/lib/perl5/site_perl/5.10.0/i386-freebsd-64int/auto/DBD/mysql/mysql.so' for module DBD::mysql: /usr/local/lib/compat/libpthread.so.2: Undefined symbol "__malloc_lock" at /usr/local/lib/perl5/5.10.0/i386-freebsd-64int/DynaLoader.pm line 203.
at (eval 4) line 3
Compilation failed in require at (eval 4) line 3.
Perhaps a required shared library or dll isn't installed where expectedЧто делать?
Заранее спасибо!
Половина ответа в вопросе.
Ты почитай, что там написано. Там написано, что что-то не установлено. Осталось найти, что ты недо установил.
Скажите кто нибудь мне пожалуйста, как правильно раcсчитать threshold. Памяти 2 Гб.