]> granicus.if.org Git - fcron/commitdiff
more comments, added some help messages, added command line options, cleaner, safer...
authorthib <thib>
Wed, 11 Jan 2006 00:55:12 +0000 (00:55 +0000)
committerthib <thib>
Wed, 11 Jan 2006 00:55:12 +0000 (00:55 +0000)
script/check_system_crontabs

index d523593841a47b28325338e93ebccb0e5e4985b5..942732b273ba0ce9aa57a78eb615b9dc15ee6f8a 100755 (executable)
 # dnotify -b -p 1 -q 0 -MCDR /etc /etc/cron.d -e /usr/local/sbin/check_system_crontabs
 # in your boot scripts.
 #
+# Because we don't want the system fcrontab to be generated every few seconds
+# if the sys admin is working in /etc/ (the script has probably been called
+# by dnotify because of a change in /etc, but it may be a file not related
+# to fcron), the script will by default sleep so as to avoid being run too
+# often. The default sleep time is 30 seconds, and can be adjusted by changing
+# DEFAULT_SLEEP_TIME_BEFORE_REBUILD below, or by passing -s X, where X is
+# the number of seconds to sleep.  X can be 0.
+#
 # If you can't use dnotify, you should run this script from the system fcrontab
 # with a line like this:
 #
-# @ 1 /usr/local/sbin/check_system_crontabs
+# @ 1 /usr/local/sbin/check_system_crontabs -s 0
+#
+# To force an immediate rebuild at the commandline try:
+#   check_system_crontabs -f -i
 #
-# and set SLEEP_TIME_BEFORE_REBUILD to 0.
+# For more help on command-line options:
+#   check_system_crontabs -h
 #
 # Changelog
 # =========
 # 2005/02/24  Thibault Godouet   Modified to be used with dnotify 
 #                                + bug fixes and enhancement.
 # 2005/04/27  Daniel Himler      Security enhancements and cleanups.
+# 2005/09/14  Damon Harper       Command lines options, cleanups.
 #
 
-CROND_DIR=/etc/cron.d
+##############################
+# DEFAULT CONFIGURATION
+
+DEFAULT_SLEEP_TIME_BEFORE_REBUILD=30
+DEFAULT_CROND_DIR=/etc/cron.d
+DEFAULT_CRONTAB_FILE=/etc/crontab
+DEFAULT_FCRONTAB_FILE=/etc/fcrontab
+
 FCRONTAB_PROG=/usr/bin/fcrontab
-CRONTAB_FILE=/etc/crontab
-FCRONTAB_FILE=/etc/fcrontab
-if [ -x `type -p mktemp` ]; then
+FCRONTABS_DIR=/var/spool/fcron
+
+# END OF DEFAULT CONFIGURATION
+##############################
+
+FCRONTAB_FILE_TMP=
+
+cleanup() {
+  # remove temporary file (if any)
+  [ -e "$FCRONTAB_FILE_TMP" ] && rm -f $FCRONTAB_FILE_TMP
+}
+trap "eval cleanup" INT TERM HUP
+
+if [ -x "`type -p mktemp`" ]; then
        FCRONTAB_FILE_TMP=`mktemp /tmp/fcrontab.XXXXXX`
 else
        FCRONTAB_FILE_TMP=/tmp/fcrontab.$$
 fi
-FCRONTABS_DIR=/var/spool/fcron
-SLEEP_TIME_BEFORE_REBUILD=30
+
+info() {
+  [ -n "$VERBOSE" ] && echo "$@" >&2
+}
+
+die() {
+  echo check_system_crontabs: "$@" >&2
+  echo Try check_system_crontabs -h for help. >&2
+  exit 1
+}
+
+usage() {
+  cat <<_EOF_ >&2
+Description: Rebuild the systab file from various system crontabs.
+Usage: check_system_crontabs [options]
+  OPTIONS:
+    -v          Verbose; tell what is happening.
+    -f          Force rebuild, even if no changes are found.
+    -s SECONDS  Sleep for SECONDS before rebuilding.
+                Default: $DEFAULT_SLEEP_TIME_BEFORE_REBUILD seconds.
+    -i          Interactive use with no delay; same as -s 0.
+    -p PATHNAME Full path to or filename of the fcrontab binary; use this
+                only if it cannot be found automatically.
+    -F FILE     System fcrontab file (default $DEFAULT_FCRONTAB_FILE).
+    -C FILE     System crontab file (default $DEFAULT_CRONTAB_FILE).
+    -D DIR      System crontab directory (default $DEFAULT_CROND_DIR).
+    -h          This help text.
+_EOF_
+  exit
+}
+
+SLEEP_TIME_BEFORE_REBUILD="$DEFAULT_SLEEP_TIME_BEFORE_REBUILD"
+CROND_DIR="$DEFAULT_CROND_DIR"
+CRONTAB_FILE="$DEFAULT_CRONTAB_FILE"
+FCRONTAB_FILE="$DEFAULT_FCRONTAB_FILE"
+FCRONTAB_PROG=
+VERBOSE=
+FORCE=
+
+# read command line arguments
+while [ "$#" -gt 0 ]; do
+  case "$1" in
+  -v)
+    VERBOSE=true
+    ;;
+  -f)
+    FORCE=true
+    ;;
+  -s)
+    SLEEP_TIME_BEFORE_REBUILD="$2"
+    shift
+    ;;
+  -i)
+    SLEEP_TIME_BEFORE_REBUILD=0
+    ;;
+  -p)
+    FCRONTAB_PROG="$2"
+    shift
+    ;;
+  -F)
+    FCRONTAB_FILE="$2"
+    shift
+    ;;
+  -C)
+    CRONTAB_FILE="$2"
+    shift
+    ;;
+  -D)
+    CROND_DIR="$2"
+    shift
+    ;;
+  -h)
+    usage
+    ;;
+  *)
+    die "Invalid option: $1!"
+    ;;
+  esac
+  shift
+done
+
+# find fcrontab executable path
+if [ -n "$FCRONTAB_PROG" ]; then
+  [ -d "$FCRONTAB_PROG" ] && FCRONTAB_PROG="$FCRONTAB_PROG/fcrontab"
+  [ ! -x "$FCRONTAB_PROG" ] && die "Invalid fcrontab executable or path specified with -p!"
+else
+  if [ -x "`type -p fcrontab`" ]; then
+    FCRONTAB_PROG="`type -p fcrontab`"
+  elif [ -x /usr/bin/fcrontab ]; then
+    FCRONTAB_PROG=/usr/bin/fcrontab
+  elif [ -x /usr/local/bin/fcrontab ]; then
+    FCRONTAB_PROG=/usr/local/bin/fcrontab
+  else
+    die "Unable to locate fcrontab binary! Specify with -p."
+  fi
+fi
+
+# sanity check
+if [ -z "$CROND_DIR" -o -z "$CRONTAB_FILE" -o -z "$FCRONTAB_FILE" ]; then
+  die "Must specify all system crontab files."
+fi
+
+# Function to scan for valid files in $CROND_DIR
+crond_files()
+{
+  [ ! -d $CROND_DIR ] && return
+  local FILES=`echo $CROND_DIR/*`
+  local FILE
+  [ "$FILES" = "$CROND_DIR/*" ] && return
+  for FILE in $FILES; do
+    if [ ! -d $FILE -a $FILE = "${FILE%\~}" ]; then
+      echo $FILE
+    fi
+  done
+}
+
 
 # Function to build up a system crontab and tell fcron it's changed
 rebuild_and_notify()
@@ -79,23 +224,21 @@ rebuild_and_notify()
   echo -e "# the $CRONTAB_FILE, the $FCRONTAB_FILE and $CROND_DIR/* files whenever one of" >> $FCRONTAB_FILE_TMP
   echo -e "# those files is changed.\n#\n\n" >> $FCRONTAB_FILE_TMP
 
-  # include the standard system crontab file if it is not a symbolic link
-  if [ ! -L $CRONTAB_FILE ]; then
+  # include the standard system crontab file if it exists and is not a symbolic link
+  if [ -f $CRONTAB_FILE -a ! -L $CRONTAB_FILE ]; then
     echo -e "\n\n########################################\n# $CRONTAB_FILE\n########################################\n" >> $FCRONTAB_FILE_TMP
     cat $CRONTAB_FILE >> $FCRONTAB_FILE_TMP
   fi
 
   # print a nice filename header for each file in /etc/cron.d/
   # and include its contents into the new fcron system crontab
-  for i in $CROND_DIR/* ; do
-    if [ $i != "RCS" ] ; then
-      echo -e "\n\n########################################\n# $i\n########################################\n" >> $FCRONTAB_FILE_TMP
-      cat $i >> $FCRONTAB_FILE_TMP
-    fi
+  for i in `crond_files` ; do
+    echo -e "\n\n########################################\n# $i\n########################################\n" >> $FCRONTAB_FILE_TMP
+    cat $i >> $FCRONTAB_FILE_TMP
   done
 
-  # include the system fcrontab file if it is not a symbolic link
-  if [ ! -L $FCRONTAB_FILE ]; then
+  # include the system fcrontab file if it exists and is not a symbolic link
+  if [ -f $FCRONTAB_FILE -a ! -L $FCRONTAB_FILE ]; then
     echo -e "\n\n########################################\n# $FCRONTAB_FILE\n########################################\n" >> $FCRONTAB_FILE_TMP
     cat $FCRONTAB_FILE >> $FCRONTAB_FILE_TMP
   fi
@@ -109,47 +252,74 @@ rebuild_and_notify()
 
 NEED_REBUILD=0
 
-# change to the directory of cron files
-cd $CROND_DIR
-
-# We don't want the system fcrontab to be generated every few seconds
-# if the sys admin is working in /etc/ (we have probably been called
-# because of a change in /etc, but it may be a file not related to fcron),
-# so we sleep so as to avoid this script be run too often.
-sleep $SLEEP_TIME_BEFORE_REBUILD
+# by default, sleep to avoid too numerous executions of this script by dnotify.
+if [ -n "$SLEEP_TIME_BEFORE_REBUILD" -a "$SLEEP_TIME_BEFORE_REBUILD" != 0 ]; then
+  if ! sleep $SLEEP_TIME_BEFORE_REBUILD; then
+    # sleep time was invalid or sleep interrupted by signal!
+    cleanup
+    exit 1
+  fi
+fi
 
-# This test works for file creation/deletion (deletion is not detected
-# by the next test)
-if [ $CROND_DIR -nt $FCRONTABS_DIR/systab.orig ]; then
+# First check if we're forcing a rebuild:
+if [ -n "$FORCE" ]; then
 
   NEED_REBUILD=1
 
 else
 
-  # Test each one and see if it's newer than our timestamp file
-  for i in $CROND_DIR/* ; do
-    if [ $i != "RCS" ]; then
-      if [ $i -nt $FCRONTABS_DIR/systab.orig ]; then
+  if [ -d $CROND_DIR ]; then
+    # This test works for file creation/deletion (deletion is not detected
+    # by the next test)
+    if [ $CROND_DIR -nt $FCRONTABS_DIR/systab.orig ]; then
+
+      info "Changes detected in $CROND_DIR"
+      NEED_REBUILD=1
+
+    else
+
+      # Test each one and see if it's newer than our timestamp file
+      for i in `crond_files` ; do
+        if [ $i -nt $FCRONTABS_DIR/systab.orig ]; then
+
+          info "Changes detected in $CROND_DIR"
+          NEED_REBUILD=1
 
-        NEED_REBUILD=1
+        fi
+      done
 
-      fi
     fi
-  done
 
-fi
+  fi
 
-# Test the standard /etc/crontab file and see if it has changed
-if [ $NEED_REBUILD -eq 0 -a \( $CRONTAB_FILE -nt $FCRONTABS_DIR/systab.orig -o $FCRONTAB_FILE -nt $FCRONTABS_DIR/systab.orig \) ]; then
+  # Test the standard /etc/crontab file and see if it has changed
+  if [ -f $CRONTAB_FILE -a $CRONTAB_FILE -nt $FCRONTABS_DIR/systab.orig ]; then
 
-  NEED_REBUILD=1
+    info "Changes detected in $CRONTAB_FILE"
+    NEED_REBUILD=1
+
+  fi
+
+  # Test the standard /etc/fcrontab file and see if it has changed
+  if [ -f $FCRONTAB_FILE -a $FCRONTAB_FILE -nt $FCRONTABS_DIR/systab.orig ]; then
+
+    info "Changes detected in $FCRONTAB_FILE"
+    NEED_REBUILD=1
+
+  fi
 
 fi
 
 if [ $NEED_REBUILD -eq 1 ]; then
 
+  info "Rebuilding fcron systab."
   rebuild_and_notify
 
+elif [ -n "$VERBOSE" ]; then
+
+  info "Not rebuilding fcron systab; no changes found."
+
 fi
 
-rm -f $FCRONTAB_FILE_TMP
+cleanup