From 0b6d1bc80d62a0ca9cfa1d1a06b167cd5eb936dd Mon Sep 17 00:00:00 2001 From: Darold Gilles Date: Fri, 28 Feb 2014 15:45:41 +0100 Subject: [PATCH] Prevents the script to run multiple instances using a pid file. This patch adds a new command line option -P to change the default pid file (/tmp/squid-analyzer.pid). Thanks to Gaetan Slongo for the patch. --- SquidAnalyzer.pm | 21 +++++++++++++++++---- squid-analyzer | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/SquidAnalyzer.pm b/SquidAnalyzer.pm index feb2ee0..0509f91 100644 --- a/SquidAnalyzer.pm +++ b/SquidAnalyzer.pm @@ -38,7 +38,7 @@ $BZCAT_PROG = "/bin/bzcat"; $RM_PROG = "/bin/rm"; # DNS Cache -my %CACHE = {}; +my %CACHE = (); # Color used to draw grpahs my @GRAPH_COLORS = ('#6e9dc9', '#f4ab3a', '#ac7fa8', '#8dbd0f'); @@ -695,11 +695,12 @@ sub _clear_stats sub _init { - my ($self, $conf_file, $log_file, $debug, $rebuild) = @_; + my ($self, $conf_file, $log_file, $debug, $rebuild, $pidfile) = @_; # Prevent for a call without instance if (!ref($self)) { print STDERR "ERROR - init : Unable to call init without an object instance.\n"; + unlink("$pidfile"); exit(0); } @@ -711,7 +712,7 @@ sub _init $conf_file = 'squidanalyzer.conf'; } } - my %options = &parse_config($conf_file, $log_file, $rebuild); + my %options = $self->parse_config($conf_file, $log_file, $rebuild); # Configuration options $self->{MinPie} = $options{MinPie} || 2; @@ -732,6 +733,7 @@ sub _init $self->{UseClientDNSName} = $options{UseClientDNSName} || 0; $self->{DNSLookupTimeout} = $options{DNSLookupTimeout} || 0.0001; $self->{DNSLookupTimeout} = int($self->{DNSLookupTimeout} * 1000000); + $self->{pidfile} = $pidfile || '/tmp/squid-analyzer.pid'; if ($self->{Lang}) { open(IN, "$self->{Lang}") or die "ERROR: can't open translation file $self->{Lang}, $!\n"; @@ -1326,6 +1328,7 @@ sub _read_stat } else { print STDERR "ERROR: bad format at line $i into $self->{Output}/$path/stat_user.dat:\n"; print STDERR "$l\n"; + unlink($self->{pidfile}); exit 0; } $i++; @@ -1353,6 +1356,7 @@ sub _read_stat } else { print STDERR "ERROR: bad format at line $i into $self->{Output}/$path/stat_user_url.dat\n"; print STDERR "$l\n"; + unlink($self->{pidfile}); exit 0; } $i++; @@ -1403,6 +1407,7 @@ sub _read_stat } else { print STDERR "ERROR: bad format at line $i into $self->{Output}/$path/stat_network.dat\n"; print STDERR "$l\n"; + unlink($self->{pidfile}); exit 0; } $i++; @@ -1435,6 +1440,7 @@ sub _read_stat } else { print STDERR "ERROR: bad format at line $i into $self->{Output}/$path/stat_netuser.dat\n"; print STDERR "$l\n"; + unlink($self->{pidfile}); exit 0; } $i++; @@ -1467,6 +1473,7 @@ sub _read_stat } else { print STDERR "ERROR: bad format at line $i into $self->{Output}/$path/stat_code.dat\n"; print STDERR "$l\n"; + unlink($self->{pidfile}); exit 0; } $i++; @@ -1487,6 +1494,7 @@ sub _read_stat } else { print STDERR "ERROR: bad format at line $i into $self->{Output}/$path/stat_mime_type.dat\n"; print STDERR "$l\n"; + unlink($self->{pidfile}); exit 0; } $i++; @@ -3413,7 +3421,7 @@ sub _gen_summary sub parse_config { - my ($file, $log_file, $rebuild) = @_; + my ($self, $file, $log_file, $rebuild) = @_; die "FATAL: no configuration file!\n" if (!-e $file); @@ -3433,26 +3441,31 @@ sub parse_config # Check config if (!exists $opt{Output} || !-d $opt{Output}) { print STDERR "Error: you must give a valid output directory. See option: Output\n"; + unlink($self->{pidfile}); exit 0; } if ( !$opt{LogFile} || !-f $opt{LogFile} ) { if (!$rebuild) { print STDERR "Error: you must give a valid path to the Squid log file. See LogFile or option -l\n"; + unlink($self->{pidfile}); exit 0; } } if (exists $opt{DateFormat}) { if ( ($opt{DateFormat} !~ m#\%y#) || (($opt{DateFormat} !~ m#\%m#) && ($opt{DateFormat} !~ m#\%M#) )|| ($opt{DateFormat} !~ m#\%d#) ) { print STDERR "Error: bad date format: $opt{DateFormat}, must have \%y, \%m or \%M, \%d. See DateFormat option.\n"; + unlink($self->{pidfile}); exit 0; } } if ($opt{Lang} && !-e $opt{Lang}) { print STDERR "Error: can't find translation file $opt{Lang}. See option: Lang\n"; + unlink($self->{pidfile}); exit 0; } if ($opt{ImgFormat} && !grep(/^$opt{ImgFormat}$/, 'png','jpg')) { print STDERR "Error: unknown image format. See option: ImgFormat\n"; + unlink($self->{pidfile}); exit 0; } return %opt; diff --git a/squid-analyzer b/squid-analyzer index 1aad8ea..0298ed5 100644 --- a/squid-analyzer +++ b/squid-analyzer @@ -19,6 +19,8 @@ my $debug = 0; my $version = 0; my $build_date = ''; my $no_year_stat = 0; +my $pid_dir = '/tmp'; +my $pidfile = 'squid-analyzer.pid'; # get the command line parameters my $result = GetOptions ( @@ -29,6 +31,7 @@ my $result = GetOptions ( "l|logfile=s" => \$logfile, "r|rebuild!" => \$rebuild, "p|preserve=i" => \$preserve, + "P|pid_dir=s" => \$pid_dir, "v|version!" => \$version, "no-year-stat!" => \$no_year_stat, ); @@ -62,8 +65,38 @@ if ($help) { exit; } +# Check if an other process is already running +if (-e "$pid_dir/$pidfile") { + die "FATAL: pid file ($pid_dir/$pidfile) exists, an other squid-analalyzer process may still running.\n"; +} + +# Write the pid file +open(OUT, ">$pid_dir/$pidfile") or die "FATAL: can not write to pid file $pid_dir/$pidfile, $!\n"; +print OUT "$$"; +close(OUT); + +# Die cleanly on signal +sub terminate +{ + # block signal + local $SIG{TERM} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + + print("LOG: Received terminating signal.\n"); + if (-e "$pid_dir/$pidfile") { + unlink("$pid_dir/$pidfile") or print("ERROR: Unable to remove pid file $pid_dir/$pidfile, $!\n"); + } + + exit 0; +} + +# Die on kill -2, -3 or -15 +$SIG{'INT'} = $SIG{'QUIT'} = $SIG{'TERM'} = 'terminate'; + + # Instanciate SquidAnalyzer.pm perl module -my $sa = new SquidAnalyzer($configfile, $logfile, $debug, $rebuild); +my $sa = new SquidAnalyzer($configfile, $logfile, $debug, $rebuild, "$pid_dir/$pidfile"); $sa->{no_year_stat} = $no_year_stat; @@ -85,6 +118,9 @@ if ($rebuild) { # Generate graphics and html $sa->buildHTML(); +# Remove PID file +unlink("$pid_dir/$pidfile"); + exit(0); @@ -103,6 +139,8 @@ Usage: squid-analyzer [ -c squidanalyzer.conf ] [-l logfile] By default: /var/log/squid/access.log -p | --preserve number : used to set the statistic obsolescence in number of month. Older stats will be removed. + -P | --pid_dir directory : set directory where pid file will be stored. + Default /tmp/ -r | --rebuild : use this option to rebuild all html and graphs output from all data files. -v | version : show version and exit.