#!/bin/sh # # Author: Todd Stansell # $Id: cron-edit,v 1.10 2005-06-15 14:18:18-07 todd Exp $ # # cron-edit # # add/remove/monitor the crontab entry # # manages crontab entries by adding the following to crontab: # # # BEGIN_cron-edit_ # # Do not modify, managed by VCS # # ... # # END_cron-edit_ # # This is intended for use with VCS 1.3.0 and above as an Application # type. Here is an example Application Agent: # # # hares -display cron_ora # ... # cron_ora CleanProgram global # cron_ora MonitorProcesses global # cron_ora MonitorProgram global /tools/custom/bin/cron-edit \ # -u oracle -t ora -C # cron_ora PidFiles global # cron_ora StartProgram global /tools/custom/bin/cron-edit \ # -u oracle -t ora -a /oracle/.crontabs/cron_ora # cron_ora StopProgram global /tools/custom/bin/cron-edit \ # -u oracle -t ora -r # cron_ora User global # BASE=`basename $0` tag=none action=none config= verbose= user= success=0 fail=1 before=/tmp/$BASE$$-before after=/tmp/$BASE$$-after begin="# BEGIN_cron-edit" mesg="# Do not modify the following entries. They are managed by cron-edit." end="# END_cron-edit" USAGE="usage: $BASE [-h] [-v] [-t tag] [-u user] {-a file | -r | -c | -C} -h help -v verbose -t tag tag to identify entry with (default: $tag) -u user username for crontab (no default) -a file update managed crontab entry with contents of \"file\" -r remove entire managed crontab entry -c check for entry and exit with 0 if present else 1 -C check for entry and exit with 1 if present else 0 (VCS)" # # update the cron entry with stuff in $after # # return codes: # 0 crontab edit succeeded # 1 crontab edit failed # update_cron(){ [ "$verbose" ] && diff $before $after # # This check is because crontab -e doesn't like it when # you leave the edited crontab as an empty file, so we # have to explicitly remove the user's crontab entry. # if [ ! -s $after ] ; then # # if the new config is empty, then just remove it... # [ "$verbose" ] && echo executing crontab -r $user crontab -r $user 2>/dev/null else # # otherwise, replace the crontab with $after. # if [ "$user" ] ; then [ "$verbose" ] && echo "executing crontab -e $user" EDITOR="cp $after" VISUAL="cp $after" \ crontab -e $user >/dev/null else [ "$verbose" ] && echo "executing crontab $after" crontab $after fi fi } # # check to see that the $start line is in the crontab # which assumes that the rest is there... # # return codes: # 0 begin entry was found # 1 begin entry was not found # check_entry() { # # Here we save a copy of the crontab as $before. # This is run before anything else and $before is # expected to exist to make any changes. # crontab -l $user >$before 2>/dev/null if [ ! -s $before ] ; then # no crontab entry, so it's not in there. return 1 fi cat $before | grep "^$begin\$" >/dev/null 2>&1; status=$? return $status } # # add appropriate cron-edit stuff for ... # add_entry() { remove_entry if [ $? -eq $fail ] ; then return $fail fi cp $before $after echo "$begin" >>$after echo "$mesg" >>$after cat $config >>$after echo "$end" >>$after update_cron } # # remove the cron-edit stuff for ... # remove_entry() { if check_entry ; then # # check_entry succeeded, so there *must* be # a begin/end pair # cp $before $after ed $after >/dev/null <<-EOT /^$begin\$/,/^$end\$/d w q EOT update_cron if check_entry ; then return $fail fi fi return $success } # # cleanup left over files... # cleanup() { for file in $before $after ; do [ -f $file ] && rm $file done } ############################################# # BEGIN MAIN PROGRAM ############################################# # # lets try to clean things up if we die # trap cleanup 0 1 2 3 5 15 while getopts a:u:t:rcChv c; do case $c in a) action=add; config=$OPTARG ;; u) user=$OPTARG ;; t) tag=$OPTARG ;; r) action=remove ;; c) action=check; success=0; fail=1 ;; C) action=check; success=1; fail=0 ;; v) verbose=true ;; h) echo "$USAGE" ; exit 0 ;; *) echo "$USAGE" >&2 ; exit 64 ;; esac done shift `expr $OPTIND - 1` # # make sure we're root if we specify a user. # if [ "$user" ] ; then if /bin/id | grep -v '^uid=0(' >/dev/null ; then echo "$BASE: must be run as root" >&2 exit 64 fi fi # # SunOS 5.5 and 5.5.1 is broken. Needs to be 5.6 or above. # Crontab doesn't behave as it should. It appears that it # doesn't pass standard-in to the editor... # case `/bin/uname -r` in 5.5|5.5.1) echo "SunOS `uname -r` crontab is broken." echo "This will only work on 5.6 or above." exit 64 ;; esac # # get full path to config, if no leading slash # if echo "$config" | grep "^[^/]" >/dev/null ; then # # expr returns 0, then no leading / # conf=`basename $config` dir=`dirname $config` dir=`cd $dir ; /bin/pwd` config=$dir/$conf fi # # update variables # begin="${begin}_$tag" mesg="$mesg # Entries from: $config" end="${end}_$tag" case $action in add) if [ ! -f $config ] ; then exit 1 fi add_entry exit $? ;; remove) remove_entry exit $? ;; check) if check_entry ; then exit $success else exit $fail fi ;; esac