Перл мне понравился
Как только вышел из под пальцев первый тестовый скрипт, тут же меня потянуло на написание разнообразных скриптов запуска, перезапуска, снятия статистик, коллекторов и прочего.
Нижеследующий скрипт является плодом перекапывания документации, двухдневного кодирования и содержит приемы работы с сигналами, работу с базой MySQL и распарсиванием строк лога squid, демонизированием скрипта (fork). И есессено, скрипт далек от идеала. Является легкой переработкой squid2mysql-1.0.0.
По сути это демон-коллектор из логов squid в базу.
Настройка по шагам:
создаем "трубу"
mkfifo /dev/squid
прописываем в squid.conf:
cache_access_log /dev/squid # это будет выталкивать в трубу строки лога
Ну и в самом скрипте мы будем просто читать из /dev/squid :)
Да-да, изредка сквид падает, рекомендуемый костыль - проверка в крон на наличие сквид-процесса, и , в случае необходимости, запуск. Что мы и оставим читателю в качестве упражнения.
#!/usr/bin/perl
use DBI;
use DBI::DBD;
$db_name="squidlog";
$db_user="nexus";
$db_host="balu.it.group";
$db_passwd="xxxxxx";
$output_squid_log="/home/logs/mysquid.log";
$output_log="/home/logs/squid2db.log";
$pid_file="/home/logs/squid2db.pid";
$dieFlag=1;
$reconnectFlag=0;
$start_args=$ARGV[0];
if($start_args eq "stop"){
if(-e $pid_file){
open (FP, $pid_file);
$child_pid=<FP>;
kill KILL => $child_pid;
close FP;
unlink $pid_file;
die "Child process $child_pid was killed";
} else { die "Not running ...\n"};
};
if($start_args eq "restart"){
if(-e $pid_file){
open (FP, $pid_file);
$child_pid=<FP>;
kill HUP => $child_pid;
close FP;
die "Child process $child_pid was restarted";
} else { print "Not running ... started\n" };
};
if($start_args eq "" || $start_args eq "start"){
# check if running
if(-e $pid_file){
open (FP, $pid_file);
$child_pid=<FP>;
close FP;
if($child_pid>0){die "Child process $child_pid already running"};
};
};
$dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;",$db_user,$db_passwd,{AutoCommit=>1,RaiseError=>0,PrintError=>1});
$dbh->{mysql_auto_reconnect}=1;
appendfile($output_log, "mysql connection ...\n");
$SIG{'HUP'} = $SIG{'ALRM'} = 'HUPHandler';
$SIG{'KILL'} = 'KILLHandler';
open (FILEHANDLE, "/dev/squid");
&Daemonize;
while($dieFlag){
if($reconnectFlag){
&Reconnect();
# clear reconnect flag
$reconnectFlag=0;
};
$data = readline(FILEHANDLE);
chop($data);
# print OUTLOG $data;
@lines=split(' ',$data);
$sth=$dbh->prepare("INSERT INTO logger(date,time,elapsed,bill,code,\
status,bytes,url,userident,host,urn)\
VALUES(?,?,?,?,?,?,?,?,?,?,?)");
# timestamp
$lines[0]=~tr/./ /;
@_timestamp=split(' ',$lines[0]);
$cts=$_timestamp[0];
# date=
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($cts);
$year=$year+1900;
$mon=$mon+1;
$hour=$hour+3;
if ($hour>24) {
$hour=$hour-24;
$mday=$mday+1;
}
$cdate="$year-$mon-$mday";
# time=
$ctime="$hour:$min:$sec";
# elapsed=
$duration=$lines[1];
# host=
$remotehost=$lines[2];
@codestatus=split('/',$lines[3]);
if ($codestatus[0] eq "TCP_HIT") { $_code=0; }
if ($codestatus[0] eq "TCP_MISS") { $_code=1; }
if ($codestatus[0] eq "TCP_REFRESH_HIT") { $_code=2; }
if ($codestatus[0] eq "TCP_REF_FAIL_HIT") { $_code=3; }
if ($codestatus[0] eq "TCP_REFRESH_MISS") { $_code=4; }
if ($codestatus[0] eq "TCP_CLIENT_REFRESH_MISS") { $_code=5; }
if ($codestatus[0] eq "TCP_IMS_HIT") { $_code=6; }
if ($codestatus[0] eq "TCP_SWAPFILE_MISS") { $_code=7; }
if ($codestatus[0] eq "TCP_NEGATIVE_HIT") { $_code=8; }
if ($codestatus[0] eq "TCP_MEM_HIT") { $_code=9; }
if ($codestatus[0] eq "TCP_DENIED") { $_code=10; }
if ($codestatus[0] eq "TCP_OFFLINE_HIT") { $_code=11; }
if ($codestatus[0] eq "UDP_HIT") { $_code=12; }
if ($codestatus[0] eq "UDP_MISS") { $_code=13; }
if ($codestatus[0] eq "UDP_DENIED") { $_code=14; }
if ($codestatus[0] eq "UDP_INVALID") { $_code=15; }
if ($codestatus[0] eq "UDP_MISS_NOFETCH") { $_code=16; }
if ($codestatus[0] eq "NONE") { $_code=17; }
# status=
$_status=$codestatus[1];
# bytes=
$objectsize=$lines[4];
# bill=
$bill=(($duration/60000)*($valueperhour/60))+(($objectsize/1048576)*$valuepermeg);
# method=
$fetchmethod=$lines[5];
#
$URLlink=$lines[6];
### for index
$URLlink =~ m/:\/\/(.+?)\//;
$urn = $1;
# $urn=$URLlink;
$username=$lines[7];
@peerstatus_host=split('/',$lines[8]);
$peerstatus=$peerstatus_host[0];
$peerhost=$peerstatus_host[1];
$objecttype=$lines[9];
############################################################
##
## transfer data to mysql table
##
############################################################
##if (($_code ne "10")&&($username ne "-")&&($_status ne "404")&&($_status ne "400")) {
if (($_code ne "10")&&($_status ne "404")&&($_status ne "400")) {
$sth->execute($cdate,
$ctime,
$duration,
$bill,
$_code,
$_status,
$objectsize,
$URLlink,
$username,
$remotehost,
$urn) || &Reconnect;
$aff="SELECT * FROM rdnload WHERE userident='$username' AND date='$cdate'";
$rows_affected=$dbh->do($aff);
if ($rows_affected < 1) {
$stn=$dbh->prepare("INSERT INTO rdnload(userident,date,download) VALUES (?,?,?)");
$stn->execute($username,$cdate,$objectsize);
}
$aff="UPDATE rdnload SET download=download+$objectsize WHERE userident='$username' AND date='$cdate'";
$rows_affected=$dbh->do($aff);
}
};
$dbh->disconnect;
close FILEHANDLE;
exit;
sub Daemonize {
print "Daemonizing phone2db ...";
open(STDIN,"</dev/null");
open(STDOUT,">/dev/null");
open(STDERR, '>&STDOUT');
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
umask 0;
open(FP,">$pid_file");
print FP $$;
close FP;
print " [ OK ]\n";
}
sub Reconnect {
$dbh->disconnect;
sleep 5;
$dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;",$db_user,$db_passwd,{AutoCommit=>1,RaiseError=>0,PrintError=>1});
appendfile($output_log,"\nreconnect occured\n");
}
sub HUPHandler {
# &Reconnect;
$reconnectFlag=1;
appendfile($output_log, "HUP signal handled\n");
}
sub KILLHandler {
appendfile($output_log, "KILL signal handled");
## Kill process
$dieFlag=0;
}
sub appendfile {
my ($fp, $msg) = @_;
if (open(FILE, ">>$fp")) {
print FILE ("$msg\n");
close FILE;
}
}
sub usage{
print "Usage: start|stop|restart\n";
}
# 0 timestamp.millisec
# 1 duration
# 2 remotehost
# 3 code/status
# 4 bytes
# 5 method
# 6 URL
# 7 username
# 8 peerstatus/peerhost
# 9 type
Оставить комментарий