admin@cs.exeter.ac.uk (Khalid Sattar) (10/02/90)
A while back I picked up a shell script called agelog from the net. This allowed a convient way of trimming logfiles. Based on that idea I have rewritten the script in perl with many more options. The most useful (to me) is compression of old logfiles. Comments and suggestions welcomed #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 10/02/1990 10:38 UTC by admin@expya # Source directory /u4/src/cyclelog # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 2782 -rw-r----- cyclelog.8 # 4329 -rwxr-x--x cyclelog # # ============= cyclelog.8 ============== if test -f 'cyclelog.8' -a X"$1" != X"-c"; then echo 'x - skipping cyclelog.8 (File already exists)' else echo 'x - extracting cyclelog.8 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cyclelog.8' && .\" -*-nroff-*- .\" eg of a TH .\" .TH submit 1 local "Updated: 20/09/90" "Exeter University" .TH CYCLELOG 8 local "Updated: 20/Sep/90" "Exeter University" .SH NAME cyclelog - roll logfile within a given range .SH SYNOPSIS cyclelog [options] logfile\d1\u [logfile\d2\u ... ] .SH DESCRIPTION \fBcyclelog\fR is a program to help maintain logfiles within the system. Many programs generate large logfiles (eg syslog). From time to time these files have to be trimmed to stop filling up of disk space. \fBcyclelog\fR rolls the specified files by moving the original \fIlogfile\fR to \fIlogfile\fR.1 and copying /dev/null to the original file. In fact you can specify how many old files to keep (see option -n below) which means that you will have logfile.1 \(-> logfile.\fIn\fR. .LP Logfile can optionally be compressed and you can also specify from which logfile to start (this is useful if you have other summary generating programs that work on recent logfiles). .SH OPTIONS .IP "-\fBn\fR \fInum\fR" How many logfiles to keep, 1 \(-> \fInum\fR. It will thus roll \fIlogfile\fR.n-1 \(-> \fIlogfile\fR.n ... \fIlogfile\fR to \fIlogfile\fR.1. The default value is 1. If \fIn\fR is 0 then simply the original logfile will be truncated to 0 but no rolling is done (i.e. no \fIlogfile\fR.1 etc.) .IP "-\fBd\fR \fIdir\fR" The directory where to stash the logfiles. The default is the same directory where the original logfile is. .IP "-\fBo\fR \fIowner\fR" Set the owner of the logfiles to \fIowner\fR. .IP "-\fBg\fR \fIgroup\fR" Set the group of the logfiles to \fIgroup\fR. .IP "-\fBz\fR" Keep the logifiles in compressed form. .IP "-\fBs\fR \fIn\fR" If compression mode is on then start compression from logfile \fIn\fR. The default is 1. .IP "-\fBm\fR mode" The mode of the logfile is \fImode\fR (give octal representation). If this option is not specifed then the mode of the original logfile is used. .IP "-\fBv\fR" Verbose mode - tells you what its doing. .IP "-\fBV\fR" Prints version number and then exits. .SH EXAMPLES To keep upto 8 logfile of the syslog file in /usr/spool/log directory. .nf X X cyclelog -n 8 /usr/spool/log/syslog X .fi Keep 4 log files of \fBlog\fR and \fBerrlog\fR from /usr/lib/news directory. The logfiles are to be kept in /usr/local/logs with mode 640 and logfiles from 3 onwards are kept in compressed form: .nf X X cyclelog -n 4 -d /usr/local/logs -m 640 -z -s 3 /usr/lib/news/{log,errlog} X .fi Thus the following files will be maintained in /usr/local/logs .nf X X log.1, log.2, log.3.Z, log.4.Z X errlog.1, errlog.2, errlog.3.Z, errlog.4.Z .fi .SH BUGS Files that are too small to be compressed are simply renamed to have a \&.Z suffix. This can be confusing. .SH AUTHOR K.Sattar@uk.ac.exeter.cs .br Computer Science Dept. .br University of Exeter SHAR_EOF chmod 0640 cyclelog.8 || echo 'restore of cyclelog.8 failed' Wc_c="`wc -c < 'cyclelog.8'`" test 2782 -eq "$Wc_c" || echo 'cyclelog.8: original size 2782, current size' "$Wc_c" fi # ============= cyclelog ============== if test -f 'cyclelog' -a X"$1" != X"-c"; then echo 'x - skipping cyclelog (File already exists)' else echo 'x - extracting cyclelog (Text)' sed 's/^X//' << 'SHAR_EOF' > 'cyclelog' && #!/usr/bin/perl -- # -*-Perl-*- # # cyclelog - roll log file within a give number. Thus logfile.n-1 # => logfile.n, logfile.n-2 => logfile.n-1 ... logfile => # logfile.1. # # -z compress # -s n start compression of files from nth logfile # -n n keep n file starting at 1 .. n # -d dir keep the logfile in dir directory # -v verbose mode # -V print version and exit # -m mode mode of the logfile # -g grp group of the log file # -o owner owner of the logfile # X #*** config part for different systems $copy = "/bin/cp"; $compress = "/usr/ucb/compress"; #*** end config X do 'getopts.pl'; &Getopts("o:m:g:zn:d:s:Vv"); X die '$Header: cyclelog,v 1.2 90/09/20 10:28:46 admin Exp $'."\n" if $opt_V; X # map owner to its uid if ($opt_o) { @entry=getpwnam($opt_o); if ($#entry == -1) { die "There is no user called \"$opt_o\"\n"; } print "Owner setting: \"$opt_o\" maps to uid $entry[2]\n" if $opt_v; $opt_o = $entry[2]; } X # map group to its gid if ($opt_g) { @entry=getgrnam($opt_g); if ($#entry == -1) { die "There is no group called \"$opt_g\"\n"; } print "Group setting: \"$opt_g\" maps to uid $entry[2]\n" if $opt_v; $opt_g = $entry[2]; } X if ($opt_m) { # convert mode given in octal to decimal $opt_m = oct($opt_m); } X $max = (defined($opt_n)) ? $opt_n : 1; # how many logfiles, 1 ... n $zstart = ($opt_s) ? $opt_s : 1; # if compressing then where to # start compression from X # for each logfile specified - roll while ($file = shift) { print ">>> $file\n" if $opt_v; if (-e $file) { $dir = &setdir($file,$opt_d); &roll($file,$dir,$max); } else { warn "\t$file does not exist\n"; } } # determine where the logfile are going to be statched X sub setdir { local($file,$dir) = @_; X if (!$dir) { if ($file =~ /(.*\/).*/) { $dir = $1; } else { $dir = "./"; } } if ($dir !~ /\/$/) { $dir .= "/"; } X if (! -w $dir) { warn "\t\"$dir\" - does not exist or is not writable - set to /tmp.\n"; $dir = "/tmp/"; } print "\tlogdir is \"$dir\"\n" if $opt_v; $dir; } X # roll the file sub roll { local($file,$dir,$max) = @_; local($older,$error,$filepart,$dest) = ($max,0,'',''); # get just the filename - /a/b/c/d => d if ($file =~ /.*\//) { $filepart = $'; # ' ignore this comment } else { $filepart = $file; } X $dest = "$dir$filepart"; while ($older> 1) { $old = $older - 1; if ($opt_z) { if ($older > $zstart) { $sz = ".Z"; $dz = ".Z"; } elsif ($older == $zstart && -f "$dest.$old") { system("$compress $dest.$old"); if (($? >> 8) == 2) { # get exit value of compress $sz = ""; } else { $sz = ".Z"; } $dz = ".Z"; } else { $sz = ""; $dz = ""; } } if (-f "$dest.$old$sz") { print "\tmv $dest.$old$sz => $dest.$older$dz\n" if $opt_v; rename("$dest.$old$sz","$dest.$older$dz") || X warn "rename of $dest.$old$sz => $dest.older$dz failed: $!\n"; } $older--; } if (-f $file) { if ($max > 0) { print("\t$copy $file $dest.1\n") if $opt_v; system("$copy $file $dest.1"); if (($? >> 8) == 0) { X @entry = stat($file); X if ($opt_o || $opt_g) { X $owner = ($opt_o) ? $opt_o : $entry[4]; X $group = ($opt_g) ? $opt_g : $entry[5]; X printf "\tchown and group to $owner and $group\n" if $opt_v; X chown($owner,$group,"$dest.1") || warn "\tchown failed: $!\n"; X } X if ($opt_m) { X chmod($opt_m,"$dest.1"); X printf("\tchmod %0o $dest.1\n",$opt_m) if $opt_v; X } else { X printf("\tchmod %0o $dest.1\n",$entry[2]) if $opt_v; X chmod($entry[2],"$dest.1") || warn "\tchmod failed: $!\n"; X } X if ($opt_z && $zstart == 1) { X system("$compress $dest.1"); X print("\t$compress $dest.1\n") if $opt_v; X if (($? >> 8) == 2) { # get exit value of compress rename("$dest.1","$dest.1.Z"); print("\tDidn't compress, mv $dest.1 => $dest.1.Z\n") if $opt_v; } X } } else { warn "\tcopy of $file to $dest.1 failed: $!\n"; $error=1; } } if (! $error) { system("$copy /dev/null $file"); print("\t$copy /dev/null $file\n") if $opt_v; } } } SHAR_EOF chmod 0751 cyclelog || echo 'restore of cyclelog failed' Wc_c="`wc -c < 'cyclelog'`" test 4329 -eq "$Wc_c" || echo 'cyclelog: original size 4329, current size' "$Wc_c" fi exit 0 -- Khalid Sattar JANET : K.Sattar@uk.ac.exeter.cs Computer Science Dept. UUCP : K.Sattar@expya.uucp University of Exeter INTERNET : K.Sattar@cs.exeter.ac.uk Exeter, UK. Tel : +44 392 264062