]> git.decadent.org.uk Git - dak.git/blobdiff - config/debian/cronscript
Adjust cronscripts to end up with just one
[dak.git] / config / debian / cronscript
diff --git a/config/debian/cronscript b/config/debian/cronscript
new file mode 100755 (executable)
index 0000000..ffaf977
--- /dev/null
@@ -0,0 +1,235 @@
+#!/bin/bash
+# No way I try to deal with a crippled sh just for POSIX foo.
+
+# Copyright (C) 2009-2015 Joerg Jaspert <joerg@debian.org>
+#
+# This program 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; version 2.
+#
+# This program 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 program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Homer: Are you saying you're never going to eat any animal again? What
+#        about bacon?
+# Lisa: No.
+# Homer: Ham?
+# Lisa: No.
+# Homer: Pork chops?
+# Lisa: Dad, those all come from the same animal.
+# Homer: Heh heh heh. Ooh, yeah, right, Lisa. A wonderful, magical animal.
+
+# exit on errors
+set -e
+set -o pipefail
+# make sure to only use defined variables
+set -u
+# ERR traps should be inherited from functions too. (And command
+# substitutions and subshells and whatnot, but for us the functions is
+# the important part here)
+set -E
+
+# And use one locale, no matter what the caller has set
+export LANG=C
+export LC_ALL=C
+
+ARG=${1:-"meh"}
+# While this check can be done in the following case, some assumptions
+# down there are easier if we sorted out calls without an arg before.
+if [[ ${ARG} == meh ]]; then
+    cat - <<EOF
+This is the FTPMaster cronscript. It needs an argument or it won't do
+anything for you.
+
+Currently accepted Arguments:
+
+   unchecked - Process the unchecked queue
+   dinstall  - Run a dinstall
+   hourly, daily, weekly - Run that part
+
+EOF
+    exit 0
+fi
+
+# Make sure we start out with a sane umask setting
+umask 022
+
+# import the general variable set.
+export SCRIPTVARS=/srv/ftp-master.debian.org/dak/config/debian/vars
+. $SCRIPTVARS
+
+# common functions are "outsourced"
+. "${configdir}/common"
+
+# program name is the (lower cased) first argument.
+PROGRAM="${ARG,,}"
+
+# Timestamp when we started
+NOW=$(date "+%Y.%m.%d-%H:%M:%S")
+
+# Which list of tasks should we run?
+TASKLIST="${configdir}/${PROGRAM}.tasks"
+
+# A logfile for every cron script
+LOGFILE="${logdir}/${PROGRAM}_${NOW}.log"
+
+# Each "cronscript" may have a variables and a functions file
+# that we source
+for what in variables functions; do
+    if [[ -f ${configdir}/${PROGRAM}.${what} ]]; then
+        . ${configdir}/${PROGRAM}.${what}
+    fi
+done
+
+# Get rid of tempfiles at the end
+trap cleanup EXIT TERM HUP INT QUIT
+
+case ${ARG,,} in
+    unchecked)
+        # Do not run during dinstall
+        if [[ -e ${LOCK_DAILY} ]]; then
+            exit 0;
+        fi
+        # only run one cron.unchecked and also lock against hourly (newoverview)
+        if ! lockfile -r8 ${LOCK_UNCHECKED} 2> /dev/null; then
+            # log "aborting cron.unchecked because $LOCK_UNCHECKED has already been locked"
+            exit 0
+        fi
+        TEMPFILES="${TEMPFILES} ${LOCK_UNCHECKED}"
+        ;;
+    dinstall)
+        ;;
+    hourly)
+        # Only one of me should ever run.
+        FLOCKER=${FLOCKER:-""}
+        [  "${FLOCKER}"  != "${configdir}/${PROGRAM}.variables" ] && exec env FLOCKER="${configdir}/${PROGRAM}.variables" flock -E 0 -en "${configdir}/${PROGRAM}.variables" "$0"
+        "$@" || :
+        ;;
+    daily)
+        ;;
+    weekly)
+        ;;
+    monthly)
+        ;;
+    *)
+        error "Unknown arg ${ARG}"
+        exit 42
+    ;;
+esac
+
+# An easy access by name for the current log
+ln -sf ${LOGFILE} ${PROGRAM}
+
+# And from here, all output to the log please
+exec >> "$LOGFILE" 2>&1
+
+# The stage function uses this directory
+# This amends the stagedir variable from "vars"
+stagedir="${stagedir}/${PROGRAM}"
+# Ensure the dir exists
+mkdir -p ${stagedir}
+
+# This loop simply wants to be fed by a list of values (see below)
+# made out of 5 columns.
+# The first four are the array values for the stage function, the
+# fifth tells us if we should background the stage call.
+#
+#  - FUNC - the function name to call
+#  - ARGS - Possible arguments to hand to the function. Can be the empty string
+#  - TIME - The timestamp name. Can be the empty string
+#  - ERR  - if this is the string false, then the call will be surrounded by
+#           set +e ... set -e calls, so errors in the function do not exit
+#           dinstall. Can be the empty string, meaning true.
+#  - BG   - Background the function stage?
+#
+# ATTENTION: Spaces in arguments or timestamp names need to be escaped by \
+#
+# NOTE 1: There are two special values for the first column (FUNC).
+#         STATE   - do not call stage function, call the state
+#                   function to update the public statefile "where is dinstall"
+#         NOSTAGE - do not call stage function, call the command directly.
+#
+# Note 2: If you want to hand an empty value to the stage function,
+#         use the word "none" in the list below.
+while read FUNC ARGS TIME ERR BACKGROUND; do
+    debug "FUNC: $FUNC ARGS: $ARGS TIME: $TIME ERR: $ERR BG: $BACKGROUND"
+
+    # Empty values in the value list are the string "none" (or the
+    # while read loop won't work). Here we ensure that variables that
+    # can be empty, are empty if the string none is set for them.
+    for var in ARGS TIME; do
+        if [[ ${!var} == none ]]; then
+            typeset ${var}=''
+        fi
+    done
+
+    # ERR/BACKGROUND are boolean, check that they are.
+    for var in ERR BACKGROUND; do
+        if [[ ${!var} != false ]] && [[ ${!var} != true ]]; then
+            error "Illegal value ${!var} for ${var} (should be true or false), line for function ${FUNC}"
+        fi
+    done
+
+    case ${FUNC} in
+        STATE)
+            state ${ARGS}
+        ;;
+        NOSTAGE)
+            ${ARGS}
+        ;;
+        *)
+            GO=(
+                FUNC=${FUNC}
+                TIME=${TIME}
+                ARGS=${ARGS}
+                ERR=${ERR}
+            )
+            if [[ ${BACKGROUND} == true ]]; then
+                stage $GO &
+            else
+                stage $GO
+            fi
+        ;;
+    esac
+done < <(grep -v '^#' ${TASKLIST} )
+
+# we need to wait for the background processes before the end of the cron script
+wait
+
+
+# Common to all cron scripts
+log "Cron script successful, all done"
+# Redirect output to another file, as we want to compress our logfile
+# and ensure its no longer used
+exec > "$logdir/after${PROGRAM}.log" 2>&1
+
+case ${ARG,,} in
+    unchecked)
+        ;;
+    dinstall)
+        logstats ${LOGFILE}
+        state "all done"
+        touch "${DINSTALLEND}"
+        ;;
+    hourly)
+        ;;
+    daily)
+        ;;
+    weekly)
+        ;;
+    monthly)
+        ;;
+esac
+
+# Now, at the very (successful) end of this run, make sure we remove
+# our stage files, so the next dinstall run will do it all again.
+rm -f ${stagedir}/*
+bzip2 -9 ${LOGFILE}
+# FIXME: Mail the log when its non-empty
+[[ -s "${logdir}/after${PROGRAM}.log" ]] || rm "${logdir}/after${PROGRAM}.log"