#!/bin/bash # ====================[ run-crons ]==================== # [ Time-stamp: "2008-12-01 16:16:12 leycec" ] # # If run as "root" (e.g., from the system crontab), this script examines # "/etc/cron.[hourly|daily|weekly|monthly]/" for scripts to be executed and # stores metadata about that last execution in "/var/spool/cron/lastrun". # # Otherwise, this script examines # "~/cron.[hourly|daily|weekly|monthly]/" for scripts to be executed and # stores metadata about that last execution in "~/var/spool/cron/lastrun". # # --------------------( CHANGELOG )-------------------- # 27 Apr 2008; Brian Curry run-crons: # Replaced the path-specific (e.g., "/etc/") segments of this script with # path-agnostic configurability. Previously, primly due to those path- # specific segments, this script could only be called from the system # crontab (e.g., "/etc/crontab") to act on system-specific paths (e.g., # "/etc/cron.daily/"); now, given the replacement of those paths with # path-agnostic configurability, this script may be called from both system # and user crontabs (e.g., "/etc/crontab" and "~/.crontab") to act on # both system- and user-specific paths (e.g., "/etc/cron.daily/" and # "~/etc/cron.daily/"). # # 08 Mar 2005; Aaron Walker run-crons: # Ignore the error messages from find caused by race conditions, since # we could care less about the error as long as the file has been removed. # See bug 8506. # # 06 May 2004; Aron Griffis run-crons: # Make the locking actually work. The old code was racy. # Thanks to Mathias Gumz in bug 45155 for some cleanups. # # 23 Jun 2002; Jon Nelson run-crons: # fixed a race condition, where cron jobs and run-crons wanted to # delete touch files # # 20 Apr 2002; Thilo Bangert run-crons: # moved lastrun directory to /var/spool/cron/lastrun # # Author: Achim Gottinger # # Mostly copied from SuSE # ....................{ VARIABLES }.................... # Run cron job processes under this "niceness." Niceness is an integer # describing the CPU scheduling priority to be allocated a process; it ranges # from -20 (the most favorable priority) to 19 (the least favorable priority). # # By default, cron job processes are run with least favorable priority so as to # minimize the CPU load on all other running processes. NICENESS=19 # Run cron job processes under this "ioniceness" and ioniceness class. # Ioniceness is a pair of integers describing the I/O scheduling priority to be # allocated a process; the ioniceness class is either 1 (the most favorable # priority, called "real time"), 2 (the normal priority, called "best effort), # or 3 (the lowest priority, called "idle"), while the ioniceness itself is an # integer ranging from 0 (the most favorable priority) to 7 (the least favorable # priority). # # By default, cron job processes are run with least favorable priority so as to # minimize the I/O load on all other running processes - but not the "idle" # priority, as that could prevent a cron job process from running at or near its # scheduled time. IONICENESS_CLASS=2 IONICENESS=7 # ....................{ LOCK FILES }.................... WHOAMI=$(whoami) if [[ "$WHOAMI" == "root" ]]; then LOGDIR=/var/log/crond LOCKDIR=/var/spool/cron/lastrun CRONROOT=/etc/cron. else LOGDIR=${HOME}/var/log/cron LOCKDIR=${HOME}/var/spool/cron/lastrun CRONROOT=${HOME}/etc/cron. fi mkdir -p ${LOGDIR} mkdir -p ${LOCKDIR} LOCKFILE=${LOCKDIR}/lock # Make sure we're not running multiple instances at once. # Try twice to lock, otherwise give up. for ((i = 0; i < 2; i = i + 1)); do ln -sn $$ ${LOCKFILE} 2>/dev/null && break # lock failed, check for a running process. # handle both old- and new-style locking. cronpid=$(readlink ${LOCKFILE} 2>/dev/null) || cronpid=$(cat ${LOCKFILE} 2>/dev/null) || continue # lockfile disappeared? try again # better than kill -0 because we can verify that it's really # another run-crons process if [[ $(/dev/null; then # whoa, another process is really running exit 0 else rm -f ${LOCKFILE} fi done # Check to make sure locking was successful if [[ ! -L ${LOCKFILE} ]]; then echo "Can't create or read existing ${LOCKFILE}, giving up" exit 1 fi # Set a trap to remove the lockfile when we're finished trap "rm -f ${LOCKFILE}" 0 1 2 3 15 # ....................{ CRON JOBS }.................... # Determine whether this system provides "nice". NICE=$(which nice 2>/dev/null) if [[ $? = 0 -a -x "$NICE" ]] then NICE="$NICE -n${NICENESS}" else NICE="" fi # Determine whether this system provides "ionice". IONICE=$(which ionice 2>/dev/null) if [[ $? = 0 -a -x "$IONICE" ]] then IONICE="$IONICE -c${IONICENESS_CLASS} -n${IONICENESS}" else IONICE="" fi for BASE in hourly daily weekly monthly ; do CRONDIR=${CRONROOT}${BASE} test -d $CRONDIR || continue if [ -e ${LOCKDIR}/cron.$BASE ] ; then case $BASE in hourly) #>= 1 hour, 5 min -=> +65 min TIME="-cmin +65" ;; daily) #>= 1 day, 5 min -=> +1445 min TIME="-cmin +1445" ;; weekly) #>= 1 week, 5 min -=> +10085 min TIME="-cmin +10085" ;; monthly) #>= 31 days, 5 min -=> +44645 min TIME="-cmin +44645" ;; esac find ${LOCKDIR} -name cron.$BASE $TIME -exec rm {} \; &>/dev/null || true fi # if there is no touch file, make one then run the scripts if [ ! -e ${LOCKDIR}/cron.$BASE ] ; then touch ${LOCKDIR}/cron.$BASE set +e for SCRIPT in $CRONDIR/* ; do if [[ -x $SCRIPT && ! -d $SCRIPT ]]; then $NICE $IONICE $SCRIPT >> "$LOGDIR"/$(basename "$SCRIPT") 2>&1 fi done fi done # Clean out bogus cron.$BASE files with future times touch ${LOCKDIR} find ${LOCKDIR} -newer ${LOCKDIR} -exec /bin/rm -f {} \; &>/dev/null || true # --------------------( COPYRIGHT AND LICENSE )-------------------- # The information below applies to everything in this distribution, # except where noted. # # This file is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This file is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this file; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.