home *** CD-ROM | disk | FTP | other *** search
- #! /bin/sh
- # savelog - save a log file
- # Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
- # Copyright (C) 1992 Ronald S. Karr
- # Slight modifications by Ian A. Murdock <imurdock@gnu.ai.mit.edu>:
- # * uses `gzip' rather than `compress'
- # * doesn't use $savedir; keeps saved log files in the same directory
- # * reports successful rotation of log files
- # * for the sake of consistency, files are rotated even if they are
- # empty
- # More modifications by Guy Maor <maor@debian.org>:
- # * cleanup.
- # * -p (preserve) option
- #
- # usage: savelog [-m mode] [-u user] [-g group] [-t] [-p] [-c cycle] [-l]
- # file...
- # -m mode - chmod log files to mode
- # -u user - chown log files to user
- # -g group - chgrp log files to group
- # -c cycle - save cycle versions of the logfile (default: 7)
- # -t - touch file
- # -l - don't compress any log files (default: compress)
- # -p - preserve mode/user/group of original file
- # file - log file names
- #
- # The savelog command saves and optionally compresses old copies of files.
- # Older version of 'file' are named:
- #
- # 'file'.<number><compress_suffix>
- #
- # where <number> is the version number, 0 being the newest. By default,
- # version numbers > 0 are compressed (unless -l prevents it). The
- # version number 0 is never compressed on the off chance that a process
- # still has 'file' opened for I/O.
- #
- # If the 'file' does not exist and -t was given, it will be created.
- #
- # For files that do exist and have lengths greater than zero, the following
- # actions are performed.
- #
- # 1) Version numered files are cycled. That is version 6 is moved to
- # version 7, version is moved to becomes version 6, ... and finally
- # version 0 is moved to version 1. Both compressed names and
- # uncompressed names are cycled, regardless of -t. Missing version
- # files are ignored.
- #
- # 2) The new file.1 is compressed and is changed subject to
- # the -m, -u and -g flags. This step is skipped if the -t flag
- # was given.
- #
- # 3) The main file is moved to file.0.
- #
- # 4) If the -m, -u, -g, -t, or -p flags are given, then the file is
- # touched into existence subject to the given flags. The -p flag
- # will preserve the original owner, group, and permissions.
- #
- # 5) The new file.0 is changed subject to the -m, -u and -g flags.
- #
- # Note: If no -m, -u, -g, -t, or -p is given, then the primary log file is
- # not created.
- #
- # Note: Since the version numbers start with 0, version number <cycle>
- # is never formed. The <cycle> count must be at least 2.
- #
- # Bugs: If a process is still writing to the file.0 and savelog
- # moved it to file.1 and compresses it, data could be lost.
- # Smail does not have this problem in general because it
- # restats files often.
-
- # common location
- export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin
- COMPRESS="gzip -9f"
- DOT_Z=".gz"
-
- # parse args
- exitcode=0 # no problems to far
- prog=`basename $0`
- mode=
- user=
- group=
- touch=
- preserve=
- count=7
-
- usage()
- {
- echo "Usage: $prog [-m mode][-u user][-g group][-t][-c cycle][-l][-p] file ..."
- }
-
-
- fixfile()
- {
- if [ -n "$user" ]; then
- chown "$user" "$1"
- fi
- if [ -n "$group" ]; then
- chgrp "$group" "$1"
- fi
- if [ -n "$mode" ]; then
- chmod "$mode" "$1"
- fi
- }
-
-
- while getopts m:u:g:c:ltph opt ; do
- case "$opt" in
- m) mode="$OPTARG" ;;
- u) user="$OPTARG" ;;
- g) group="$OPTARG" ;;
- c) count="$OPTARG" ;;
- t) touch=1 ;;
- l) COMPRESS="" ;;
- p) preserve=1 ;;
- h) usage; exit 0 ;;
- *) usage; exit 1 ;;
- esac
- done
-
- shift $(($OPTIND - 1))
-
- if [ "$count" -lt 2 ]; then
- echo "$prog: count must be at least 2" 1>&2
- exit 2
- fi
-
- # cycle thru filenames
- while [ $# -gt 0 ]; do
-
- # get the filename
- filename="$1"
- shift
-
- # catch bogus files
- if [ -e "$filename" -a ! -f "$filename" ]; then
- echo "$prog: $filename is not a regular file" 1>&2
- exitcode=3
- continue
- fi
-
- # if not a file or empty, do nothing major
- # (in the Debian version, we rotate even if empty)
- #if [ ! -s $filename ]; then
- # if -t was given and it does not exist, create it
- if [ -n "$touch" -a ! -f "$filename" ]; then
- touch "$filename"
- if [ "$?" -ne 0 ]; then
- echo "$prog: could not touch $filename" 1>&2
- exitcode=4
- continue
- fi
- fixfile "$filename"
- fi
- # continue
- #fi
-
- # be sure that the savedir exists and is writable
- # (in the Debian version, $savedir is . and not ./OLD)
- savedir=`dirname "$filename"`
- if [ -z "$savedir" ]; then
- savedir=.
- fi
- if [ ! -d "$savedir" ]; then
- mkdir "$savedir"
- if [ "$?" -ne 0 ]; then
- echo "$prog: could not mkdir $savedir" 1>&2
- exitcode=5
- continue
- fi
- chmod 0755 "$savedir"
- fi
- if [ ! -w "$savedir" ]; then
- echo "$prog: directory $savedir is not writable" 1>&2
- exitcode=7
- continue
- fi
-
- # determine our uncompressed file names
- newname=`basename "$filename"`
- newname="$savedir/$newname"
-
- # cycle the old compressed log files
- cycle=$(( $count - 1))
- rm -f "$newname.$cycle" "$newname.$cycle$DOT_Z"
- while [ $cycle -gt 1 ]; do
- # --cycle
- oldcycle=$cycle
- cycle=$(( $cycle - 1 ))
- # cycle log
- if [ -f "$newname.$cycle$DOT_Z" ]; then
- mv -f "$newname.$cycle$DOT_Z" \
- "$newname.$oldcycle$DOT_Z"
- fi
- if [ -f "$newname.$cycle" ]; then
- # file was not compressed. move it anyway
- mv -f "$newname.$cycle" "$newname.$oldcycle"
- fi
- done
-
- # compress the old uncompressed log if needed
- if [ -f "$newname.0" ]; then
- if [ -z "$COMPRESS" ]; then
- newfile="$newname.1"
- mv "$newname.0" "$newfile"
- else
- newfile="$newname.1$DOT_Z"
- # $COMPRESS < $newname.0 > $newfile
- # rm -f $newname.0
- $COMPRESS "$newname.0"
- mv "$newname.0$DOT_Z" "$newfile"
- fi
- fixfile "$newfile"
- fi
-
- # create new file if needed
- if [ -n "$preserve" ]; then
- cp -p "$filename" "$filename.new"
- echo -n > "$filename.new"
- filenew=1
- elif [ -n "$touch$user$group$mode" ]; then
- touch "$filename.new"
- fixfile "$filename.new"
- filenew=1
- fi
-
- # link the file into the file.0 holding place
- if [ -f "$filename" ]; then
- if [ -n "$filenew" ]; then
- ln -f "$filename" "$newname.0"
- mv "$filename.new" "$filename"
- else
- mv "$filename" "$newname.0"
- fi
- fi
- [ ! -f "$newname.0" ] && touch "$newname.0"
- fixfile "$newname.0"
-
- # report successful rotation
- echo "Rotated \`$filename' at `date`."
- done
- exit $exitcode
-