git-svn-id: svn+ssh://svn.ipng.nl/usr/share/subversion/repositories/irc.efnet.nl@7 0a436592-62d7-4152-98a5-b7e29e440240
330 lines
9.2 KiB
Bash
Executable File
330 lines
9.2 KiB
Bash
Executable File
#!/usr/local/bin/bash
|
|
|
|
# Original author: Pim van Pelt <pim@bit.nl>
|
|
# Taken from OSS publication upstream:
|
|
# debit.bit.nl:/debian/dists/stable/main/binary-i386/bit-cron-1.9-20060627.02.deb
|
|
# and modified for use at Google.
|
|
#
|
|
# Author: Pim van Pelt <pim@google.com>
|
|
|
|
# This is the master cron file format. It is designed to be quiet
|
|
# and not shout anything at all to stdout/stderr in normal use.
|
|
#
|
|
# Usage: bitcron [-n] /path/to/crondefinition.cron [arg [arg ..]]
|
|
#
|
|
# This program eats either one or two arguments from the commandline.
|
|
# If -n is given as the first argument, output is sent to stdout rather
|
|
# than MAILTO or ESCALATE_MAILTO (this is a `dryrun'). The next argument
|
|
# is a filename consisting of the cron definition. The file is sourced
|
|
# and executed, but within a framework that makes crons much easier to
|
|
# live with. You SHOULD have the filename of your crondefinition end
|
|
# in ".cron", so it is apparent to other people that this is indeed
|
|
# a cron definition. All other arguments are passed to the crontab's
|
|
# main function, called bitcron_main; see below.
|
|
#
|
|
# The cron definition file consists of the following shell variables:
|
|
#
|
|
# PATH: Optional. You can set a standard path for your cron to search
|
|
# programs in. Note that cron sets a minimal path, so you probably need
|
|
# this if you are going to call programs from weird places.
|
|
# Example: PATH=$PATH
|
|
#
|
|
# AUTHOR: Mandatory. Your full name, so we can track the author in case
|
|
# something goes horribly wrong.
|
|
# Example: AUTHOR="Pim van Pelt"
|
|
#
|
|
# NAME: Mandatory. The name of your script. This MUST be a terse
|
|
# descriptive name consisting of [A-Za-z0-9\-\_], and in particular
|
|
# no whitespace. It's used in logs and mails.
|
|
# Example: NAME="example"
|
|
#
|
|
# MASTERLOG: Optional. If this is set, the transcript of the log is copied
|
|
# to this file upon completion. If it is not set, the transcript is silently
|
|
# deleted. Please make sure that this filename is writable for the calling
|
|
# user, and that its name reveals who wrote it (including $NAME is a good
|
|
# idea.
|
|
# Example: MASTERLOG="/var/log/cron-${NAME}.log"
|
|
#
|
|
# MAILTO: Optional. If this is set, the transcript of the log is mailed to
|
|
# this user using /usr/sbin/sendmail -t, in the event of no warnings,
|
|
# errors, or fatal errors, aka 'if all went well'. If it is not set, the
|
|
# mail is not sent on succesful completion of this cronjob. Please use
|
|
# with care if your cron runs often.
|
|
# Example: MAILTO="pim+noise@google.com"
|
|
#
|
|
# ESCALATE_MAILTO: Mandatory. If this is set, the transcript of the log
|
|
# is mailed to this user using /usr/sbin/sendmail -t, in the event of
|
|
# any warning, error or fatal error, aka 'if anything borked'. Please
|
|
# make sure that this address is not a single person, but rather a role
|
|
# account. This ensures better closure and continuity.
|
|
# Example: ESCALATE_MAILTO="maps-alerts@google.com"
|
|
#
|
|
# Variables your script MUST NOT change are:
|
|
# ERR, WRN, HOSTNAME, FATAL, FQDN
|
|
#
|
|
# Your cron-definition does not shebang. It begins with these variables.
|
|
# It then has at least one function called bitcron_main(), in which you write
|
|
# your cron just like you normally would, but each step is prepended by a
|
|
# short oneliner describing what you are doing and appended with a line
|
|
# stating you are done doing it, followed by an empty line.
|
|
#
|
|
# In your bitcron_main() script, you have three functions at your disposal:
|
|
# warning $TEXT
|
|
# error $TEXT
|
|
# fatal $TEXT
|
|
#
|
|
# where warning() prints the TEXT and increments the warning counter, error()
|
|
# increments the error counter and fatal() increments the error counter and
|
|
# immediately halts execution of the cron.
|
|
#
|
|
# For example:
|
|
# bitcron_main()
|
|
# {
|
|
# echo "Running rsync"
|
|
# rsync blabla || warning "Could not rsync"
|
|
# echo "Done (rsync)"
|
|
# echo ""
|
|
#
|
|
# echo "Doing something crucial"
|
|
# /usr/local/bin/crucial.sh blabla || \
|
|
# fatal "Could not do the crucial stuff, aborting!"
|
|
# echo "Done (crucial)"
|
|
# echo ""
|
|
#
|
|
# echo "Succesfully executed the cron"
|
|
# }
|
|
#
|
|
# In the event of a fatal error (retval of crucial.sh != 0), the line
|
|
# 'echo "Done (crucial)"' will not be executed, rather the cronscript
|
|
# stops and mails to the escalation mail address that there was a serious
|
|
# error which needs human intervention.
|
|
#
|
|
# Return values of bitcron depend on the presence of errors or warnings.
|
|
# If there are no errors nor warnings, 0 is returned to the calling shell.
|
|
# If there are errors, 127 is returned. If there are no errors, but there
|
|
# are warnings, 126 is returned. If you somewhere set the RETVAL variable
|
|
# (which is optional), that value is returned instead.
|
|
#
|
|
# Please note that your bitcron_main() function MUST NOT use exit. This messes up
|
|
# the clean execution of this script, prohibiting it from mailing or
|
|
# returning a decent exitcode to the calling shell.
|
|
#
|
|
|
|
# BITCRON_SEARCHPATH="/usr/local/cronscripts/ /etc/cronscripts/ ./"
|
|
BITCRON_SEARCHPATH="~/cronscripts/ ./"
|
|
BITCRON_REPORTTOOL="/usr/sbin/sendmail -t"
|
|
|
|
function fatal()
|
|
{
|
|
echo ""
|
|
echo "===== FATAL ====="
|
|
echo $1
|
|
echo "===== FATAL ====="
|
|
ERR=$(($ERR + 1))
|
|
FATAL=1;
|
|
bitcron_end
|
|
}
|
|
|
|
function error()
|
|
{
|
|
echo ""
|
|
echo "===== ERROR ====="
|
|
echo $1
|
|
echo "===== ERROR ====="
|
|
ERR=$(($ERR + 1))
|
|
}
|
|
|
|
function warning()
|
|
{
|
|
echo ""
|
|
echo "===== WARNING ====="
|
|
echo $1
|
|
echo "===== WARNING ====="
|
|
WRN=$(($WRN + 1))
|
|
}
|
|
|
|
function bitcron_report()
|
|
{
|
|
if [ $WRN -eq 0 -a $ERR -eq 0 ]; then
|
|
if [ ! -z "$MAILTO" ]; then
|
|
(
|
|
echo "From: $HOSTNAME $NAME <`whoami`@$FQDN>"
|
|
echo "To: $MAILTO"
|
|
echo "Subject: bitcron $NAME - succesful"
|
|
echo "Date: `date '+%a, %d %b %Y %T %z'`"
|
|
echo "Errors-To: $MAILTO"
|
|
echo "Reply-To: $MAILTO"
|
|
echo "X-bitcron: $NAME"
|
|
echo "X-Precedence: automatic"
|
|
echo ""
|
|
echo "Dear reader,"
|
|
echo ""
|
|
echo "This is the $0 program on $HOSTNAME informing"
|
|
echo "you I have succesfully executed the bitcron $NAME."
|
|
echo ""
|
|
echo "The log that I have for this cronjob follows:"
|
|
cat $LOG
|
|
echo ""
|
|
echo "This mail is purely FYI, user intervention is not required."
|
|
echo ""
|
|
echo "-- "
|
|
echo "Cheers,"
|
|
echo " $HOSTNAME"
|
|
) | ${BITCRON_REPORTTOOL}
|
|
fi
|
|
else
|
|
(
|
|
echo "From: $HOSTNAME $NAME <`whoami`@$FQDN>"
|
|
echo "To: $ESCALATE_MAILTO"
|
|
if [ ! -z "$MAILTO" ]; then
|
|
echo "CC: $MAILTO"
|
|
fi
|
|
if [ $FATAL -eq 0 ]; then
|
|
echo "Subject: bitcron $NAME - $ERR error(s), $WRN warning(s)"
|
|
else
|
|
echo "Subject: bitcron $NAME - FATAL - $ERR error(s), $WRN warning(s)"
|
|
fi
|
|
echo "Date: `date '+%a, %d %b %Y %T %z'`"
|
|
echo "Errors-To: $ESCALATE_MAILTO"
|
|
echo "Reply-To: $ESCALATE_MAILTO"
|
|
echo "X-Precedence: automatic"
|
|
echo "X-bitcron: $NAME"
|
|
echo "X-Errors: $ERR"
|
|
echo "X-Warnings: $WRN"
|
|
echo ""
|
|
echo "Dear reader,"
|
|
echo ""
|
|
echo "This is the $0 program on $HOSTNAME informing"
|
|
echo "you that there was a problem running the bitcron $NAME."
|
|
echo ""
|
|
echo "The logfile that lead up to this:"
|
|
cat $LOG
|
|
echo ""
|
|
echo "I hope you can deal with this situation ASAP."
|
|
echo ""
|
|
echo "-- "
|
|
echo "Cheers,"
|
|
echo " $HOSTNAME"
|
|
) | ${BITCRON_REPORTTOOL}
|
|
fi
|
|
}
|
|
|
|
function bitcron_begin()
|
|
{
|
|
if [ -z "$MASTERLOG" ]; then
|
|
LOG="/tmp/bitcron-$NAME.$$"
|
|
else
|
|
LOG="${MASTERLOG}.$$"
|
|
fi
|
|
rm -f -- $LOG
|
|
exec 3>&1 4>&2 1>$LOG 2>&1
|
|
WRN=0
|
|
ERR=0
|
|
FATAL=0
|
|
FQDN=$(hostname)
|
|
HOSTNAME=$(hostname -s)
|
|
if [ "A`echo $FQDN | grep '\.'`" = "A" ]; then
|
|
FQDN="${FQDN}.corp.google.com"
|
|
fi
|
|
|
|
echo "Beginning $NAME cronjob at `date`"
|
|
echo ""
|
|
}
|
|
|
|
function bitcron_end()
|
|
{
|
|
echo ""
|
|
echo "Done with $NAME cronjob at `date`"
|
|
echo ""
|
|
echo "There were $ERR error(s) and $WRN warning(s)"
|
|
if [ $FATAL -ne 0 ]; then
|
|
echo "This script had a fatal error!"
|
|
fi
|
|
|
|
exec 1>&3 2>&4
|
|
|
|
bitcron_report
|
|
|
|
if [ ! -z "$MASTERLOG" ]; then
|
|
cp -f -- "$LOG" "$MASTERLOG"
|
|
fi
|
|
rm -f -- $LOG >/dev/null 2>&1
|
|
if [ ! -z $RETVAL ]; then
|
|
exit $RETVAL
|
|
elif [ $ERR -ne 0 ]; then
|
|
exit 127
|
|
elif [ $WRN -ne 0 ]; then
|
|
exit 126
|
|
fi
|
|
exit 0
|
|
}
|
|
|
|
function bitcron_usage()
|
|
{
|
|
echo ""
|
|
echo "Usage: bitcron [-n] /path/to/crondefinition.cron [arg [arg ..]]"
|
|
echo ""
|
|
echo "Please read the bitcron script. It has documentation at the"
|
|
echo "top of the file. Look in $0 for more details."
|
|
echo "-- Author: Pim van Pelt <pim@google.com>"
|
|
}
|
|
|
|
# Here goes!
|
|
if [ $# -lt 1 ]; then
|
|
bitcron_usage
|
|
exit 128
|
|
fi
|
|
|
|
# See if we are in dryrun mode.
|
|
if [ $1 = "-n" ]; then
|
|
BITCRON_REPORTTOOL="/bin/cat"
|
|
shift
|
|
fi
|
|
|
|
BITCRON_DEFINITION=$1
|
|
shift;
|
|
#
|
|
# Search through paths if the cron definition was not an absolute path.
|
|
#
|
|
if [ ${BITCRON_DEFINITION%%/*} ]; then
|
|
for BITCRON_DIR in ${BITCRON_SEARCHPATH}; do
|
|
if [ -r ${BITCRON_DIR}${BITCRON_DEFINITION} ]; then
|
|
break;
|
|
fi
|
|
done
|
|
else
|
|
BITCRON_DIR=""
|
|
fi
|
|
|
|
if [ ! -r ${BITCRON_DIR}${BITCRON_DEFINITION} ]; then
|
|
echo "bitcron: Unreadable cron definition: ${BITCRON_DIR}${BITCRON_DEFINITION}"
|
|
if [ ${BITCRON_DEFINITION%%/*} ]; then
|
|
echo "I tried in: ${BITCRON_SEARCHPATH}"
|
|
fi
|
|
bitcron_usage
|
|
exit 128
|
|
fi
|
|
|
|
|
|
. ${BITCRON_DIR}${BITCRON_DEFINITION}
|
|
|
|
if [ -z "$NAME" ]; then
|
|
echo "bitcron: Missing mandatory variable NAME in ${BITCRON_DIR}${BITCRON_DEFINITION}"
|
|
bitcron_usage
|
|
exit 128
|
|
fi
|
|
if [ -z "$AUTHOR" ]; then
|
|
echo "bitcron: Missing mandatory variable AUTHOR in ${BITCRON_DIR}${BITCRON_DEFINITION}"
|
|
bitcron_usage
|
|
exit 128
|
|
fi
|
|
if [ -z "$ESCALATE_MAILTO" ]; then
|
|
echo "bitcron: Missing mandatory variable ESCALATE_MAILTO in ${BITCRON_DIR}${BITCRON_DEFINITION}"
|
|
bitcron_usage
|
|
exit 128
|
|
fi
|
|
|
|
bitcron_begin
|
|
bitcron_main $*
|
|
bitcron_end
|