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/