Karyn Williams wrote:

I have a sh script as follows. The script worked OK until the year rolled
over. My (now deleted) simple sh way of figuring the month and year blew
up. I decided to rewrite the script in perl because of the date/time
functions. It takes multiple commandline args (usernames) and checks for
various information on them. Since the maillogs are so large I want to exit
the first loop as soon as it is determined that the user has checked their
mail.
#!/bin/sh

ext=`date +%Y%m`

month1="200702"
month2="200701"
month3="200612"
month4=200611
month5=200610
month6=200609
month7=200608

for i in $* ; do

        echo $i

        if test -r /export/home/$i/.forward ; then echo $i has forward file
; continue ;
        elif [ "`fgrep -c "user=$i" /var/adm/maillog`" -gt "0" ] ; then
echo $i checked mail month 0 ;  continue ;
        elif [ "`fgrep -c "user=$i" /export/home/archives/maillog.$month1`"
-gt "0" ] ; then echo $i checked mail month 1 ; continue;
        elif [ "`fgrep -c "user=$i" /export/home/archives/maillog.$month2`"
-gt "0" ] ; then echo $i checked mail month 2 ; continue;
        elif [ "`fgrep -c "user=$i" /export/home/archives/maillog.$month3`"
-gt "0" ] ; then echo $i checked mail month 3 ; continue;
        elif [ "`fgrep -c "user=$i" /export/home/archives/maillog.$month4`"
-gt "0" ] ; then echo $i checked mail month 4 ; continue;
        elif [ "`fgrep -c "user=$i" /export/home/archives/maillog.$month5`"
-gt "0" ] ; then echo $i checked mail month 5 ; continue;
        elif [ "`fgrep -c "user=$i" /export/home/archives/maillog.$month6`"
-gt "0" ] ; then echo $i checked mail month 6 ; continue;
        else echo $i has not checked mail in the last 6 months ;
        fi
echo checking last for 2007 ; last -3 $i
        echo checking 2007 dial-up ; fgrep -c P${i}
/var/adm/radacct/pleiades/detail
        echo checking for last modified file ; ls -lrt /export/home/$i |
tail -2
        echo checking for newest file in public_html ; ls -lrt
/export/home/$i/public_html | tail -2 ls -lsu /export/mail/$i
        quota -v $i
        finger -m $i
done

This is what I have so far in perl:

# cat tt.pl
#!/usr/bin/perl -w

use POSIX;

# Get the current month and year
my ($mon,$year) = (localtime)[4,5];

# Seed nmonth

my @nmonth = (1,1,1,1,$mon,$year,0,0);

my $sec  =  1;
my $min  =  1;
my $hour =  1;
my $day  =  1;
my $wday =  0;
my $yday =  0;

# Put the loop here
my $a = 1;
while ($a < 7) {
my $current = mktime($sec, $min, $hour, $day, $nmonth[4],
$nmonth[5], $wday, $yday); # Make new timestamp for the first
        @nmonth = localtime($current);          # Make an array out of the
timestamp to get the month and year
        my $ext_mon = ($nmonth[4] + 1);         # Pull the month out of the
array and add 1 to get month number
        my $ext_year = ($nmonth[5] + 1900);     # Pull the year and add
1900 to get the actual year
        if ($ext_mon <= 9) {                    # Make the month have two
places and write the var $ext
                $ext = $ext_year . '0' . $ext_mon;
        }
        else {
                $ext = $ext_year . $ext_mon;
        }

        push (@flist, $ext);
        $current = $current - 86400;    # Subtract one day from the first
timestamp to get the month before
        @nmonth = localtime($current);          # Make an array out of the
new timestamp for the next round
}
continue {
        $a++;
}

# This is the part I am having trouble with :

foreach $k (@ARGV) {

if (-e ("/export/home/$k/.forward")) { print "User $k has a forward file.\n\n" ; next ;
        } else {
open MAILLOG, "/var/adm/maillog" or die "couldn't open maillog :
$!\n";
                if ($count = grep /user=$k/o, <MAILLOG> ) {
                print "$k checked mail $count times in
/var/adm/maillog.\n"; next ;
                } else {
close MAILLOG;
        open MAILLOG, "/export/home/archives/maillog.$flist[1]" or die
"couldn't open maillog.$flist[1] : $!\n";
                if ($count = grep /user=$k/o, <MAILLOG> ) {
                        print "$k checked mail $count times in
maillog.$flist[1].\n"; next ;
                } else {
close MAILLOG;
        open MAILLOG, "/export/home/archives/maillog.$flist[2]" or die
"couldn't open maillog.$flist[2] : $!\n";
                if ( $count = grep /user=$k/o, <MAILLOG> ) {
                print "$k checked mail $count times in
maillog.$flist[2].\n"; next ;
        } else {
        close MAILLOG;
open MAILLOG, "/export/home/archives/maillog.$flist[3]" or die
"couldn't open maillog.$flist[3] : $!\n";
                if ( $count = grep /user=$k/o, <MAILLOG> ) {
                print "$k checked mail $count times in
maillog.$flist[3].\n"; next ;
        } else {
        close MAILLOG;
open MAILLOG, "/export/home/archives/maillog.$flist[4]" or die
"couldn't open maillog.$flist[4] : $!\n";
                if ( $count = grep /user=$k/o, <MAILLOG> ) {
                print "$k checked mail $count times in
maillog.$flist[4].\n"; next ;
        } else {
        close MAILLOG;

        open MAILLOG, "/export/home/archives/maillog.$flist[5]" or die
"couldn't open maillog.$flist[5] : $!\n";
                if ( $count = grep /user=$k/o, <MAILLOG> ) {
                print "$k checked mail $count times in
maillog.$flist[5].\n"; next ;
        } else {
        close MAILLOG; print "$k has not checked their mail in the last 6
months.\n";

        }
        }
        }
        }
        }
        }

}
}


Input and output looks like this:

# ./tt.pl karyn smurphy root
karyn checked mail 2864 times in /var/adm/maillog.
smurphy checked mail 2864 times in /var/adm/maillog.
root checked mail 2864 times in /var/adm/maillog.
#

Yes, it goes to the next arg but as you can see, it returns the same count
for each subsequent arg.
I feel that my braces are (all/part/some) of the problem, but not sure
how/what. Any suggestions would be appreciated.

Hello Karyn

Your out of memory errors are because you are reading the entire log files
into memory before applying grep. Take a look at the program below. It's
untested as I would have had to set up a lot of data to try it out, but
I've checked it carefully and am sure it's at least pretty close.

A couple of notes:

- I've pushed a null string on to the month list in place of the current
month as it's a special case for selecting the log file to read and it makes
the logic inside the loop a little neater.

- The line $log =~ s|.*archives/||; just takes the path off the archived mail
log files so that the messages printed are the same as your own program
produced.

- If you're having speed problems with this, then it could be better written by
opening each log file once only, and checking each line for any of the users
while reading through it. But it's fine as it is if it's running OK.

Hope this helps,

Rob


use strict;
use warnings;

my ($mon,$year) = (localtime)[4,5];
$mon++;
$year += 1900;

my @months;
push @months, '';

while (@months < 6) {
 $mon--;
 unless ($mon) {
   $year--;
   $mon = 12;
 }
 push @months, sprintf "%04d%02d", $year, $mon;
}

foreach my $user (@ARGV) {

if (-e "/export/home/$user/.forward") { print "User $user has a forward file.\n\n";
   next;
 }
my $count;
 my $log;
 foreach my $month (@months) {

   $log = $month ? "/export/home/archives/maillog.$month" : '/var/adm/maillog';
   open MAILLOG, $log or die "Couldn't open maillog $log: $!";

   $count = 0;
   while (<MAILLOG>) {
     $count++ if /user=$user/;
   }
   last if $count;
 }
if ($count) {
   $log =~ s|.*archives/||;
   print "$user checked mail $count times in $log.\n";
 }
 else {
   print "$user has not checked their mail in the last 6 months.\n";
 }
}

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to