http://www.perlmonks.org?node_id=142829


in reply to Re: tail -f multiple nfs files
in thread tail -f multiple nfs files

#!/usr/bin/perl use DBI; use Time::Local; use File::Basename; use CGI::Carp qw(cluck); ########################### # SET UP GLOBALS, ETC ETC ########################### $/ = "\cM\cJ"; #FILES ARE ON AN NFS MOUNTED WINDOWS SERVER my $CURRENT = 'Starting the radius detail thingy--no record yet'; + #HOLDS ERROR INFO my $DETAIL_FILE = shift || die "Need file name w/ radius recs\n"; + #FILE FROM WHICH TO START READING RECs my $NEXT_FILE = get_next_file_name($DETAIL_FILE); + #NAME OF DETAIL AFTER MIDNIGHT my $DATABASE_HOST = shift || die "Need host w/ database\n"; + #HOST WITH DATABASE my $DATABASE = 'database=radius;' . "host=$DATABASE_HOST"; my $DEBUG = "false"; my $sleepcount = 0; ######################### # INITIALIZE ######################### #CONNECT TO THE DATABASE my $DBH = DBI->connect("dbi:Pg:dbname=radius;host=$DATABASE_HOST", "xx +xxxx", "xxxxxx", { RaiseError => 1, AutoCommit => 1, InactiveDestroy => 1} ) or + croak "Could not connect to database"; $count = 0; $SQL; open(ACCT, "$DETAIL_FILE"); #SEEK TO EOF seek(ACCT, -1024, 2); #THROW OUT FIRST LINE (MIGHT BE INCOMPLETE) $_ = <ACCT>; LOOP: for (;;) { for ($curpos = tell(ACCT); $_ = <ACCT>; $curpos = tell(ACCT)) +{ my @rec_array = split(/,/, $_); #GET RID OF USELESS TRASH foreach $_ (@rec_array){ $_ =~ s/"//g; $_ =~ s/\s//g; } #TEMP TO FIX USERNAMES WITH "Hex:" $rec_array[7] =~ s/Hex\:.*//; my $ff = substr($rec_array[8], -4); eval { if ($rec_array[3] eq "Start") { $SQL = qq/INSERT INTO online VALUES (/. qq/'$rec_array[0] $rec_array[1]',/. + #timestamp qq/'$rec_array[13]',/. #acct +_session_id qq/'$rec_array[6]',/. #nas_ +ip_address qq/'$rec_array[7]',/. #user +_name qq/'$rec_array[11]',/. #fram +ed_ip_address qq/'$rec_array[9]',/. #call +ing_station_id qq/'$rec_array[8]',/. #call +ed_station_id qq/'$ff',/. #fin +al_four qq/'$rec_array[23]'/. #nas_port qq/);/; #$count++; #print "$SQL\n"; $DBH->do($SQL) or croak "Could not Insert: ", +caller(), ":", $DBH->errstr, "\n$SQL\n"; } elsif ($rec_array[3] eq "Stop") { my $TABLE = "acct".$ff; $SQL = "DELETE FROM online WHERE acct_session_ +id='$rec_array[13]' AND nas_ip_address='$rec_array[6]'"; #print "$SQL\n"; $DBH->do($SQL) or croak "Could not delete: ", +caller(), ":", $DBH->errstr, "\n"; $SQL = qq/INSERT INTO $TABLE VALUES (/. qq/'$rec_array[0] $rec_array[1]',/. + #timestamp qq/'$rec_array[7]',/. #user_ +name qq/'$rec_array[11]',/. #frame +d_ip_address qq/'$rec_array[12]',/. #frame +d_protocol qq/'$rec_array[6]',/. #nas_i +p_address qq/'$rec_array[13]',/. #acct_ +session_id qq/'$rec_array[20]',/. #acct_ +session_time qq/'$rec_array[21]',/. #acct_ +input_packets qq/'$rec_array[22]',/. #acct_ +output_packets qq/'$rec_array[14]',/. #ascen +d_disconnect_cause qq/'$rec_array[15]',/. #ascen +d_connect_progress qq/'$rec_array[16]',/. #ascen +d_xmit_rate qq/'$rec_array[17]',/. #ascen +d_data_rate qq/'$rec_array[19]',/. #ascen +d_modem_portno qq/'$rec_array[18]',/. #ascen +d_modem_slotno qq/'$rec_array[9]',/. #calli +ng_station_id qq/'$rec_array[8]'/. #calle +d_station_id qq/);/; #print "$SQL\n"; $DBH->do($SQL) or croak "Could not Insert: ", +caller(), ":", $DBH->errstr, "\n$SQL\n"; #$count++; } }; #TRY TO RECONNECT IF ERROR USING reopen_db() if ($@) { print "Eval Error: $@ $SQL"; next LOOP; } } if (-e $NEXT_FILE){ sleep 3; #SLEEP TO ALLOW OS TO SYNC UP close(ACCT); $DETAIL_FILE = $NEXT_FILE; open (ACCT, "$DETAIL_FILE") || die "couldn't open file +: $!\n"; $NEXT_FILE = get_next_file_name($DETAIL_FILE); next; #NEXT FILE DOESN'T EXISTS, SO SLEEP AND TRY AGAIN } else { #IF NO CHANGE IN FILE FOR 60 SECS, RE-OPEN FILE if ($sleepcount > 60) { #RE-OPEN FILE THAT HAS RADIUS INFORMATION open (ACCT, "$DETAIL_FILE") || die "Couldn't o +pen $DETAIL_FILE: $!\n"; #GO ALMOST TO THE END seek(ACCT, -1024, 2); #THROW OUT FIRST LINE (MIGHT BE INCOMPLETE) $_ = <ACCT>; print "Reopened file. Position: ", tell(ACCT) + ,".FIRST LINE: $_\n"; $sleepcount = 0; next; } sleep 1; $sleepcount++; seek(ACCT, $curpos, 0); } } ##################### # EXIT AND CLEAN UP ##################### $DBH->disconnect(); close(ACCT); #print "Inserted $count"; ######################## # get_next_file_name() # DETERMINES THE NAME OF THE NEXT FILE TO TAIL FROM WHEN NEW NAME AT M +IDNIGHT # NAME OF FILE SHOULD BE LIKE `/mnt/rad-1/YYYYMMDD.act' ######################## sub get_next_file_name{ #FIND OUT WHERE FILE IS MOUNTED my $path = shift; #PARSE NAME OF FILE my ($base, $dir, $ext) = fileparse($path); #CONFIRM THAT FILE MATCHES THE NUMBER FORMAT $base =~ m/(\d\d\d\d)(\d\d)(\d\d)/ || die "Bad Filename Format +: $!\n"; #GENERATE NAME: my ($year, $month, $day) = ($1, $2, $3); #FINDS THE EPOCH SECONDS OF TODAY AT NOON my $curr_day = timelocal(0, 0, 12, $day, $month - 1, $year - 1 +900 ); #USE THAT NUMBER PLUS A DAYS WORTH OF SECONDS (86400) TO GENER +ATE TOMMORROW'S DATE NUMBERS my ($new_year, $new_month, $new_day) = (localtime($curr_day + +86399))[5, 4, 3]; #print "Opened new file: ".dirname($path).($new_year + 1900).( +$new_month + 1).$new_day."\n"; return sprintf("%s/%4.4d%2.2d%2.2d.act", dirname($path) , $new +_year + 1900, $new_month + 1, $new_day ); }