Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Created December 15, 2011 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amcgregor/1481626 to your computer and use it in GitHub Desktop.
Save amcgregor/1481626 to your computer and use it in GitHub Desktop.
Userland rich cron system for use with dcron and userland init script system.
# Set using: crontab root-crontab
59 * * * * rm -f /var/spool/cron/lastrun/cron.hourly /home/*/var/cron/lastrun/cron.hourly
9 3 * * * rm -f /var/spool/cron/lastrun/cron.daily /home/*/var/cron/lastrun/cron.daily
19 4 * * 6 rm -f /var/spool/cron/lastrun/cron.weekly /home/*/var/cron/lastrun/cron.weekly
29 5 1 * * rm -f /var/spool/cron/lastrun/cron.monthly /home/*/var/cron/lastrun/cron.monthly
39 6 1 1 * rm -f /home/*/var/cron/lastrun/cron.yearly
*/10 * * * * (test -x /usr/sbin/run-crons && /usr/sbin/run-crons); (test -x /usr/local/bin/run-user-crons && /usr/local/bin/run-user-crons)
#!/bin/bash
# Actually named: /usr/local/bin/run-user-cron.sh
LOCKDIR=${HOME}/var/cron/lastrun
LOCKFILE=${LOCKDIR}/lock
LOG=${HOME}/var/log/cron.log
SCRIPTLOGBASE=${HOME}/var/cron
mkdir -p ${LOCKDIR}
# 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 [[ $(</proc/${cronpid}/cmdline) == $(</proc/$$/cmdline) ]] 2>/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
for BASE in hourly daily weekly monthly yearly ; do
CRONDIR=${HOME}/etc/cron/${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}
mkdir -p ${SCRIPTLOGBASE}/${BASE}
rm -f ${SCRIPTLOGBASE}/${BASE}/*
set +e
for SCRIPT in ${CRONDIR}/* ; do
if [[ -x ${SCRIPT} && ! -d ${SCRIPT} ]]; then
SCRIPTLOG=${SCRIPTLOGBASE}/${BASE}/$(basename ${SCRIPT})
echo -e "[:] ${SCRIPT} $(date)\n" > ${SCRIPTLOG}
${SCRIPT} 2>&1 >> ${SCRIPTLOG}
cat ${SCRIPTLOG} >> ${LOG}
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
#!/bin/bash
# Actually named: /usr/local/bin/run-user-crons.sh
for USERHOME in /home/* ; do
test -d ${USERHOME}/etc/cron || continue
USR=$(basename ${USERHOME})
logger -t cron "Running scheduled tasks for user: ${USR}"
sudo -H -u ${USR} -n -i /usr/local/bin/run-user-cron
done
#!/bin/bash
# Actually named: /etc/local.d/user.start
for USERHOME in /home/* ; do
test -d ${USERHOME}/etc/init.d || continue
USR=$(basename ${USERHOME})
for JOB in ${USERHOME}/etc/init.d/* ; do
test -x ${JOB} || continue
sudo -H -u ${USR} -n -i ${JOB} start
done
done
#!/bin/bash
# Actually named: /etc/local.d/user.stop
for USERHOME in /home/* ; do
test -d ${USERHOME}/etc/init.d || continue
USR=$(basename ${USERHOME})
for JOB in ${USERHOME}/etc/init.d/* ; do
test -x ${JOB} || continue
sudo -H -u ${USR} -n -i ${JOB} stop
done
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment