]> git.decadent.org.uk Git - dak.git/blob - config/debian/cronscript
Adjust cronscripts to end up with just one
[dak.git] / config / debian / cronscript
1 #!/bin/bash
2 # No way I try to deal with a crippled sh just for POSIX foo.
3
4 # Copyright (C) 2009-2015 Joerg Jaspert <joerg@debian.org>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 # Homer: Are you saying you're never going to eat any animal again? What
20 #        about bacon?
21 # Lisa: No.
22 # Homer: Ham?
23 # Lisa: No.
24 # Homer: Pork chops?
25 # Lisa: Dad, those all come from the same animal.
26 # Homer: Heh heh heh. Ooh, yeah, right, Lisa. A wonderful, magical animal.
27
28 # exit on errors
29 set -e
30 set -o pipefail
31 # make sure to only use defined variables
32 set -u
33 # ERR traps should be inherited from functions too. (And command
34 # substitutions and subshells and whatnot, but for us the functions is
35 # the important part here)
36 set -E
37
38 # And use one locale, no matter what the caller has set
39 export LANG=C
40 export LC_ALL=C
41
42 ARG=${1:-"meh"}
43 # While this check can be done in the following case, some assumptions
44 # down there are easier if we sorted out calls without an arg before.
45 if [[ ${ARG} == meh ]]; then
46     cat - <<EOF
47 This is the FTPMaster cronscript. It needs an argument or it won't do
48 anything for you.
49
50 Currently accepted Arguments:
51
52    unchecked - Process the unchecked queue
53    dinstall  - Run a dinstall
54    hourly, daily, weekly - Run that part
55
56 EOF
57     exit 0
58 fi
59
60 # Make sure we start out with a sane umask setting
61 umask 022
62
63 # import the general variable set.
64 export SCRIPTVARS=/srv/ftp-master.debian.org/dak/config/debian/vars
65 . $SCRIPTVARS
66
67 # common functions are "outsourced"
68 . "${configdir}/common"
69
70 # program name is the (lower cased) first argument.
71 PROGRAM="${ARG,,}"
72
73 # Timestamp when we started
74 NOW=$(date "+%Y.%m.%d-%H:%M:%S")
75
76 # Which list of tasks should we run?
77 TASKLIST="${configdir}/${PROGRAM}.tasks"
78
79 # A logfile for every cron script
80 LOGFILE="${logdir}/${PROGRAM}_${NOW}.log"
81
82 # Each "cronscript" may have a variables and a functions file
83 # that we source
84 for what in variables functions; do
85     if [[ -f ${configdir}/${PROGRAM}.${what} ]]; then
86         . ${configdir}/${PROGRAM}.${what}
87     fi
88 done
89
90 # Get rid of tempfiles at the end
91 trap cleanup EXIT TERM HUP INT QUIT
92
93 case ${ARG,,} in
94     unchecked)
95         # Do not run during dinstall
96         if [[ -e ${LOCK_DAILY} ]]; then
97             exit 0;
98         fi
99         # only run one cron.unchecked and also lock against hourly (newoverview)
100         if ! lockfile -r8 ${LOCK_UNCHECKED} 2> /dev/null; then
101             # log "aborting cron.unchecked because $LOCK_UNCHECKED has already been locked"
102             exit 0
103         fi
104         TEMPFILES="${TEMPFILES} ${LOCK_UNCHECKED}"
105         ;;
106     dinstall)
107         ;;
108     hourly)
109         # Only one of me should ever run.
110         FLOCKER=${FLOCKER:-""}
111         [  "${FLOCKER}"  != "${configdir}/${PROGRAM}.variables" ] && exec env FLOCKER="${configdir}/${PROGRAM}.variables" flock -E 0 -en "${configdir}/${PROGRAM}.variables" "$0"
112         "$@" || :
113         ;;
114     daily)
115         ;;
116     weekly)
117         ;;
118     monthly)
119         ;;
120     *)
121         error "Unknown arg ${ARG}"
122         exit 42
123     ;;
124 esac
125
126 # An easy access by name for the current log
127 ln -sf ${LOGFILE} ${PROGRAM}
128
129 # And from here, all output to the log please
130 exec >> "$LOGFILE" 2>&1
131
132 # The stage function uses this directory
133 # This amends the stagedir variable from "vars"
134 stagedir="${stagedir}/${PROGRAM}"
135 # Ensure the dir exists
136 mkdir -p ${stagedir}
137
138 # This loop simply wants to be fed by a list of values (see below)
139 # made out of 5 columns.
140 # The first four are the array values for the stage function, the
141 # fifth tells us if we should background the stage call.
142 #
143 #  - FUNC - the function name to call
144 #  - ARGS - Possible arguments to hand to the function. Can be the empty string
145 #  - TIME - The timestamp name. Can be the empty string
146 #  - ERR  - if this is the string false, then the call will be surrounded by
147 #           set +e ... set -e calls, so errors in the function do not exit
148 #           dinstall. Can be the empty string, meaning true.
149 #  - BG   - Background the function stage?
150 #
151 # ATTENTION: Spaces in arguments or timestamp names need to be escaped by \
152 #
153 # NOTE 1: There are two special values for the first column (FUNC).
154 #         STATE   - do not call stage function, call the state
155 #                   function to update the public statefile "where is dinstall"
156 #         NOSTAGE - do not call stage function, call the command directly.
157 #
158 # Note 2: If you want to hand an empty value to the stage function,
159 #         use the word "none" in the list below.
160 while read FUNC ARGS TIME ERR BACKGROUND; do
161     debug "FUNC: $FUNC ARGS: $ARGS TIME: $TIME ERR: $ERR BG: $BACKGROUND"
162
163     # Empty values in the value list are the string "none" (or the
164     # while read loop won't work). Here we ensure that variables that
165     # can be empty, are empty if the string none is set for them.
166     for var in ARGS TIME; do
167         if [[ ${!var} == none ]]; then
168             typeset ${var}=''
169         fi
170     done
171
172     # ERR/BACKGROUND are boolean, check that they are.
173     for var in ERR BACKGROUND; do
174         if [[ ${!var} != false ]] && [[ ${!var} != true ]]; then
175             error "Illegal value ${!var} for ${var} (should be true or false), line for function ${FUNC}"
176         fi
177     done
178
179     case ${FUNC} in
180         STATE)
181             state ${ARGS}
182         ;;
183         NOSTAGE)
184             ${ARGS}
185         ;;
186         *)
187             GO=(
188                 FUNC=${FUNC}
189                 TIME=${TIME}
190                 ARGS=${ARGS}
191                 ERR=${ERR}
192             )
193             if [[ ${BACKGROUND} == true ]]; then
194                 stage $GO &
195             else
196                 stage $GO
197             fi
198         ;;
199     esac
200 done < <(grep -v '^#' ${TASKLIST} )
201
202 # we need to wait for the background processes before the end of the cron script
203 wait
204
205
206 # Common to all cron scripts
207 log "Cron script successful, all done"
208 # Redirect output to another file, as we want to compress our logfile
209 # and ensure its no longer used
210 exec > "$logdir/after${PROGRAM}.log" 2>&1
211
212 case ${ARG,,} in
213     unchecked)
214         ;;
215     dinstall)
216         logstats ${LOGFILE}
217         state "all done"
218         touch "${DINSTALLEND}"
219         ;;
220     hourly)
221         ;;
222     daily)
223         ;;
224     weekly)
225         ;;
226     monthly)
227         ;;
228 esac
229
230 # Now, at the very (successful) end of this run, make sure we remove
231 # our stage files, so the next dinstall run will do it all again.
232 rm -f ${stagedir}/*
233 bzip2 -9 ${LOGFILE}
234 # FIXME: Mail the log when its non-empty
235 [[ -s "${logdir}/after${PROGRAM}.log" ]] || rm "${logdir}/after${PROGRAM}.log"