File run-crons of Package cronie.import4562

#!/bin/bash
#
# /usr/lib/cron/run-crons
#
# Copyright (c) 1998-2001 SuSE GmbH Nuernberg, Germany. All rights reserved.
#
# this script looks into /etc/cron.{hourly,daily,weekly,monthly} for
# scripts to be executed.  The info about last run is stored in
# /var/spool/cron/lastrun
#
# concept similar to debian and redhat
#
# Changes:
#     1998 - Burchard Steinbild <bs@suse.de>, 1998
#         initial version
#     before 2001 - va@org.chemie.uni-frankfurt.de   
#        send an email with name of date-script instead of cron entry 
#         "Subject: cronjob@www - daily - FAILURE" 
#        (better one script for each date-sub-script)
#        requires changes to /etc/crontab 
#        append > /dev/null 2>&1  to the line calling run-cons 
#     2001-09-11  
#        updated to Suse 7.2 merged  
#     2001-09-12
#        changed FAILURE detection, until now all scripts with output
#        had "failed", now only scripts with error status != 0 
#        have failed.
#     2001-09-13 - ro@suse.de
#        merged with 7.3: call logger with exit value for scripts
#        respect MAILTO as cron does
#        use mktemp -d for all tmpfiles
#        add variable to disable mail if all jobs returned 0
#

#
# Don't run jobs on laptops, that are AC-offline
#
if test -x /usr/bin/on_ac_power ; then
	on_ac_power -q
	if [ "$?" = "1" ]; then
		exit 0
	fi
fi

if [ -f /etc/sysconfig/cron ]; then
	. /etc/sysconfig/cron
fi

BASENAME=`/usr/bin/basename $0`
LOGGER="/bin/logger -t $BASENAME[$$]"

export LC_TIME=POSIX
TMPDIR=`mktemp -d /tmp/run-crons.XXXXXX`
trap "rm -rf $TMPDIR" 0 1 2 3 13 15

# We will force to run cron.daily after 14 days, even
# if you set MAX_NOT_RUN in /etc/sysconfig/cron
# value is in minutes
MAX_NOT_RUN_FORCE="20160"

# Priority change for sub scripts.
# range: highest -20 ... 19 lowest prioriy
#  default processes start in level 10
CRON_SCRIPT_NICE_VALUE=15
SPOOL=/var/spool/cron/lastrun

# CRON Result EMail is sent to
if test -z "$MAILTO" ; then
  SEND_TO="root"
else
  SEND_TO="$MAILTO"
fi

mkdir -p $SPOOL

#set verbose
## stage 1,  search directories/scripts to run
RUN=""
for CRONDIR in /etc/cron.{hourly,daily,weekly,monthly} ; do
    test -d $CRONDIR || continue
    BASE=${CRONDIR##*/}
    TIME_EXT=${BASE##cron.}
    
    test -e $SPOOL/$BASE && {
        case $BASE in
          cron.hourly)  TIME="-cmin  +60 -or -cmin  60" ;;
          cron.daily) 
			# if DAILY_TIME set, run only at a fixed time of day
			if [ "$DAILY_TIME" != "" ] ; then
                          DAILY_TIME_NEW="`echo $DAILY_TIME | sed s,:,, | sed s,^0\*,, `" 
			  test -z "$DAILY_TIME_NEW" && DAILY_TIME_NEW=0
                          if [ "$DAILY_TIME_NEW" -gt "2359" ] ; then
                            echo "wrong time format in /etc/sysconfig/cron DAILY_TIME, value is $DAILY_TIME" | logger
			  fi  
                          NOW_H=`date +%H%M| sed s,^0\*,,`
			  test -z "$NOW_H" && NOW_H=0
                          if [ $DAILY_TIME_NEW -gt $(($NOW_H-15)) ] && [ $DAILY_TIME_NEW -le $NOW_H ]; then
                              TIME=""
                          else
			      # take care of MAX_NOT_RUN, default is 7 days
			      if [ "$MAX_NOT_RUN" != "0" ] ; then
                                TIME="-cmin +$((1440*$MAX_NOT_RUN)) -or -cmin $((1440*$MAX_NOT_RUN))"
			      else
				TIME="-cmin +$MAX_NOT_RUN_FORCE -or -cmin $MAX_NOT_RUN_FORCE" 
			      fi                               
                          fi 
 
			# run as usual   
			else
			  TIME="-cmin +1440 -or -cmin 1440" 
			fi ;;
          cron.weekly)  TIME="-cmin +10080 -or -cmin 10080"  ;;
          cron.monthly) 
			DAYOFMONTH=`date '+%d'`
			DAYSLASTMONTH=`date -d "-$DAYOFMONTH days" '+%d'`
			if [ $DAYOFMONTH -gt $DAYSLASTMONTH ] ; then
				LASTMONTHSTR="-$DAYOFMONTH days"
			else
				LASTMONTHSTR="last month"
			fi
			NOW=`date +%s`
			LASTMONTH=`date -d "$LASTMONTHSTR" +%s`
                        DIFF=`expr '(' $NOW - $LASTMONTH ')' / 86400`
                        TIME="-ctime +$DIFF"
                        ;;
        esac
	# remove all lock files for scripts that are due to run
        eval find $SPOOL/$BASE $TIME | \
             xargs --no-run-if-empty rm
    }
    if test ! -e $SPOOL/$BASE ; then
	# accept this dir, if it isn't empty 
	LIST=`find $CRONDIR ! -type d`
	if [ ! -z "$LIST" ] ; then
	    RUN="${RUN} ${TIME_EXT}"
	fi
    fi
done


##  STATUS communication variable between 
#     function run_scripts ()
#   and loop-over-all-scripts 
#   set in run_scripts to FAILURE if this script failed!
#   else it is empty 
#   because it is never reset to empty after the initialization
#   it implements an OR like logic over all scripts
##  
STATUS=""

# helper, run all scripts in one cron directory
function run_scripts (){
    local CRONDIR=$1
    local TIME_EXT=$2


    local TEMP_MSG=$TMPDIR/run-crons.${TIME_EXT}.$$
    rm -r $TMPDIR/run-crons.${TIME_EXT}.* >/dev/null 2>&1

    # keep going when something fails
    set +e
    for SCRIPT in $CRONDIR/* ; do
	test -d $SCRIPT && continue
	case "$SCRIPT" in
               .svn)           continue ;;
               *.rpm*)         continue ;;
               *.swap)         continue ;;
               *.bak)          continue ;;
               *.orig)         continue ;;
               \#*)            continue ;;
               *~)             continue ;;
        esac
	/sbin/checkproc $SCRIPT && continue
	if test -x $SCRIPT ; then
	    BASESCRIPT=`/usr/bin/basename $SCRIPT`

	    nice -n ${CRON_SCRIPT_NICE_VALUE} $SCRIPT >$TEMP_MSG 2>&1

	    local ERRNO=$?
	    if [ 0 -eq $ERRNO ] ; then	
		if [ "$SYSLOG_ON_NO_ERROR" = "yes" ]; then
		    echo "$BASESCRIPT: OK" | $LOGGER -p info
		fi
	    else
		echo "$BASESCRIPT returned $ERRNO" | $LOGGER -p warn
		echo "SCRIPT: $BASESCRIPT exited with RETURNCODE = $ERRNO." 
       	        STATUS="FAILURE"
	    fi
	    # write some wrapper text around the original output
	    if [ -s "$TEMP_MSG" ] ; then 
		echo "SCRIPT: output (stdout && stderr) follows"
		echo ""
		cat $TEMP_MSG 		
		echo -e "SCRIPT: $BASESCRIPT\n------- END OF OUTPUT"     
    		echo ""     
		echo ""     
	    fi  
            
	    rm -f $TEMP_MSG > /dev/null 2>&1
	else
	    echo "WARNING: $SCRIPT is not executable, script is ignored !"
	fi
    done
}

# stage 2: 
#   run all scripts  and collect output into one mail
#   for each TIME_EXT with a meaningfull subject.
#        
if [ ! -z "${RUN}"  ] ; then
    for EXT in ${RUN} ; do
	CRONDIR="/etc/cron."${EXT}
	test -d $CRONDIR || continue
	BASE=`/usr/bin/basename $CRONDIR`
	TIME_EXT=${BASE##cron.}
	STATUS=""

	if test ! -e $SPOOL/$BASE ; then
	    CONTROL_MAIL=$TMPDIR/run-crons_mail.$$
	    JOB_OUTPUT=$TMPDIR/run-crons_output.$$

	    echo "running ${TIME_EXT} cronjob scripts" >> ${CONTROL_MAIL}
	    echo "" >> ${CONTROL_MAIL}

	    touch $SPOOL/$BASE

	    run_scripts  ${CRONDIR} ${TIME_EXT} >> ${JOB_OUTPUT} 2>&1
	    TITLE="cronjob@$HOSTNAME - ${TIME_EXT}"
	    if [ -n "${STATUS}" ] ; then 
		TITLE="${TITLE} - ${STATUS}" 
            else 
                TITLE="${TITLE} - OK" 
	    fi
	    if [ -n "${STATUS}" -o "$SEND_MAIL_ON_NO_ERROR" = "yes" ] ; then
		cat ${CONTROL_MAIL} ${JOB_OUTPUT} | mail ${SEND_TO} -s "${TITLE}" 
	    elif [ -s ${JOB_OUTPUT} -a "$SEND_OUTPUT_ON_NO_ERROR" = "yes" ] ; then
		cat ${CONTROL_MAIL} ${JOB_OUTPUT} | mail ${SEND_TO} -s "${TITLE}" 
	    fi
	    
	    rm -f ${CONTROL_MAIL} ${JOB_OUTPUT}
	fi
    done
fi

#
# now make sure, we have no lastrun files dated to future
#
touch $SPOOL
NOW=`date -u +%s`
for i in `find $SPOOL -type f`
do
    FILEDATE=`date -u -r $i +%s`
    # allow for up to one hour in the future because of summer/wintertime
    if [ $((FILEDATE - NOW)) -gt 3600 ]
    then
	rm $i
    fi
done