At 03:05 PM 3/30/07 +0100, Rob Dixon wrote:
>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";
>  }
>}
>


Thanks to everyone who helped. I will spend some time analysing this and
see where I went wrong. I'm sure I'll have questions. BTW it seems to work
as is.



-- 

Karyn Williams
Network Services Manager
California Institute of the Arts
[EMAIL PROTECTED]
http://www.calarts.edu/network

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


Reply via email to