Category: Apache Administration
Author/Contact Info Eli K. Breen
Description: Looks for NIMDA requests in your Apache log files
#!/usr/bin/perl -w
# Written by Eli K. Breen
# NIMDA Apache Log Analyser
# V 1.02
#       
# 1.01 - Oct09 2001- Changed output to printf instead of print
# 1.02 - Oct30 2001- Added Date output and default log check
#
# Usage: ./MISS.PRISS.pl /some/directory/apache_access.logfile |sort
#(usually /var/log/httpd-access.log)
#
$DefaultLog = "/var/log/httpd-access.log";      # Setting default log 
+file
                                        # Without this line you need t
+o specify...
                                        #       'NIMDA.pl /somedir/som
+eapachelog'
$IPHash{"127.0.0.1"} = "0";             # Initialize the %IPHash
@DateArray = localtime; $DateArray[5] += 1900; $DateArray[4] += 1; $Da
+teArray[2] =~ s/^\d\b/0$DateArray[2]/; $DateArray[1] =~ s/^\d\b/0$Dat
+eArray[1]/;
if ( $#ARGV <= 0 ) { $ARGV[0] = $DefaultLog; print "Last Updated $Date
+Array[5]-$DateArray[4]-$DateArray[3] $DateArray[2]\:$DateArray[1].$Da
+teArray[0]\n";print STDERR "Logfile not specified, trying $DefaultLog
+...\n" };
@lineArray = (grep /cmd.exe/, <>);      # For every line in log contai
+ning 'cmd.exe'
foreach $line (@lineArray)      {       # For every occurance of 'cmd.
+exe' in array
        @splitLine = split /\ /, $line; # Grab just the IP address at 
+the begining
                $IPHash{$splitLine[0]}++
                                };
@keylist = (keys(%IPHash));
foreach $IPKey (sort @keylist)
{
        printf "%-6s %10s\n", $IPHash{$IPKey}, $IPKey;
        $IPCount += $IPHash{$IPKey};
};
#sub bytry      {       #Sort records by number of attempts
        printf "%15s %10s\n", "Total:", $IPCount;
Replies are listed 'Best First'.
Re: MISS.PRISS - NIMDA request logger
by Aristotle (Chancellor) on Jan 28, 2003 at 01:21 UTC
    Some indentation goes a long way. Excessive comments hurt more than they help. The dot in your regex is not matched literally, it's a wildcard for "(nearly) any character". You're slurping the file, which could easily lead to a lot of memory consumption on busy sites with large logfiles. Testing $#ARGV including equality to zero means you have to pass at least two parameters, since with a single element the result will be 0 and trigger your condition.
    #!/usr/bin/perl -w use strict; @ARGV = qw(/var/log/apache/access_log) unless @ARGV; my %source; while(<>) { next unless /cmd\.exe/; my ($ip) = /^(\S+)/; $source{$ip}++; } printf "%-6s %10s\n", $source{$_}, $_ for keys %source; printf "%15s %10s\n", "Total:", scalar keys %source;
    Untested.

    Makeshifts last the longest.