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/