chiark / gitweb /
Merge branch 'master' of login.chiark.greenend.org.uk:public-git/inn-innduct
[inn-innduct.git] / scripts / news.daily.in
1 #!@_PATH_SH@
2 ##  $Revision: 5999 $
3 ##  Daily news maintenance.
4 ##  Optional arguments:
5 ##      expdir=xxx      Directory in which to build new history file
6 ##      tmpdir=xxx      Working directory for `sort' and such
7 ##      expirectl=xxx   Use xxx as expire.ctl file
8 ##      flags=xxx       Pass xxx flags to expire
9 ##      lowmark         Create and use a lowmark file
10 ##      noexpire        Do not expire
11 ##      noexplog        Do not log expire output
12 ##      nologs          Do not scan logfiles
13 ##      nomail          Do not capture and mail output
14 ##      norenumber      Do not renumber the active file
15 ##      norm            Do not remove certain old files
16 ##      norotate        Do not rotate logfiles
17 ##      nostat          Do not run innstat
18 ##      notdaily        Not a daily run, and therefore implies nologs.
19 ##      delayrm         Delay unlink files, then do it quicker (expire -z)
20 ##      /full/path      Path to a program to run before expiring
21
22 . @LIBDIR@/innshellvars
23
24 EXPLOG=${MOST_LOGS}/expire.log
25 INNSTAT=${PATHBIN}/innstat
26 HOSTNAME=`hostname`
27 DATE=`date`
28 TAGGEDHASH=@DO_DBZ_TAGGED_HASH@
29 SORT=sort
30
31 ##  If your expire does not pause or throttle innd, enable this next line:
32 #MESSAGE="Expiration script $$"
33 ##  Renumber all at once, or in steps?  Set to the delay if steps (that
34 ##  may take a long time!).
35 RENUMBER=
36
37 PROGNAME=news.daily
38 LOCK=${LOCKS}/LOCK.${PROGNAME}
39
40 ##  Set defaults.
41 DAILY=true
42 DOEXPIRE=true
43 DOEXPLOG=true
44 DOEXPIREOVER=false
45 DOLOGS=true
46 DOMAIL=true
47 DORENUMBER=true
48 DORM=true
49 DOSTAT=true
50 EXPIRECTL=
51 EXPDIR=
52 EXPIREFLAGS="-v1"
53 EXPIREOVER=expireover
54 LOWMARKFILE=
55 RMFILE=
56
57 HISTDIR="`dirname ${HISTORY}`"
58 TOUT=600   # timeout value for ctlinnd commands
59 if [ -z "${HISTDIR}" -o X"." = X"${HISTDIR}" -o ! -d "${HISTDIR}" ]; then
60     if [ -d "${PATHETC}/hist" ]; then
61         HISTDIR="${PATHETC}/hist"
62     else
63         HISTDIR="${PATHETC}"
64     fi
65 fi
66 if [ "${ENABLEOVERVIEW}" = "true" ]; then
67     DOEXPIREOVER=true
68     RMFILE=${MOST_LOGS}/expire.rm
69 fi
70
71 EXPIREOVERFLAGS=
72 PROGRAMS=
73 POSTPROGRAMS=
74 REASON=
75 SCANARG=
76 DOGROUPBASEEXPIRY=false
77
78 if [ "${GROUPBASEEXPIRY}" = "true" ]; then
79     if [ "${ENABLEOVERVIEW}" = "true" ]; then
80         DOGROUPBASEEXPIRY=true
81     else
82         DOEXPIREOVER=false
83         RMFILE=
84     fi
85 fi
86
87 ##  Parse JCL.
88 for I
89 do
90     case "X$I" in
91     Xdelayrm)
92         RMFILE=${MOST_LOGS}/expire.rm
93         ;;
94     Xexpctl=*)
95         EXPIRECTL=`expr "${I}" : 'expctl=\(.*\)'`
96         case ${EXPIRECTL} in
97         /*)
98             ;;
99         *)
100             EXPIRECTL=`/bin/pwd`/${EXPIRECTL}
101             ;;
102         esac
103         ;;
104     Xexpdir=*)
105         EXPDIR=`expr "${I}" : 'expdir=\(.*\)'`
106         ;;
107     Xtmpdir=*)
108         TMPDIR=`expr "${I}" : 'tmpdir=\(.*\)'`
109         ;;
110     Xexpireover)
111         DOEXPIREOVER=true
112         RMFILE=${MOST_LOGS}/expire.rm
113         ;;
114     Xexpireoverflags=*)
115         EXPIREOVERFLAGS=`expr "${I}" : 'expireoverflags=\(.*\)'`
116         ;;
117     Xflags=*)
118         EXPIREFLAGS=`expr "${I}" : 'flags=\(.*\)'`
119         ;;
120     Xlowmark)
121         LOWMARKFILE=${MOST_LOGS}/expire.lowmark
122         DORENUMBER=false
123         ;;
124     Xnotdaily)
125         DAILY=false
126         DOLOGS=false
127         ;;
128     Xnoexpire)
129         DOEXPIRE=false
130         ;;
131     Xnoexpireover)
132         DOEXPIREOVER=false
133         RMFILE=
134         ;;
135     Xnoexplog)
136         DOEXPLOG=false
137         ;;
138     Xnologs)
139         DOLOGS=false
140         ;;
141     Xnomail)
142         DOMAIL=false
143         MAIL="cut -c 1-1022 | ${SED} -e 's/^~/~~/'"
144         ;;
145     Xnonn)
146         # Ignore this.
147         ;;
148     Xnorenumber)
149         DORENUMBER=false
150         ;;
151     Xnorm)
152         DORM=false
153         ;;
154     Xnorotate)
155         SCANARG="${SCANARG} norotate"
156         ;;
157     Xnostat)
158         DOSTAT=false
159         ;;
160     X/*)
161         PROGRAMS="${PROGRAMS} ${I}"
162         ;;
163     Xpostexec=*)
164         POSTEXEC=`expr "${I}" : 'postexec=\(.*\)'`
165         POSTPROGRAMS="${POSTPROGRAMS} ${POSTEXEC}"
166         ;;
167     *)
168         echo "Unknown flag ${I}" 1>&2
169         exit 1
170         ;;
171     esac
172 done
173
174 ##
175 ## Setup mail subject and command
176 ##
177 if ${DAILY} ; then
178    MAILSUBJ="${HOSTNAME} Daily Usenet report for ${DATE}"
179 else
180    MAILSUBJ="${HOSTNAME} intermediate usenet report for ${DATE}"
181 fi
182 MAIL="cut -c 1-1022 | ${SED} -e 's/^~/~~/' | \
183     ${MAILCMD} -s '$MAILSUBJ' ${NEWSMASTER}"
184
185 #
186 #       Sanity check. Shouldn't we just bail out here with an error
187 #       instead of trying to patch things up?
188 #
189 ${DOEXPIRE} || {
190     EXPDIR=
191     RMFILE=
192 }
193
194 test -n "${EXPDIR}" && {
195         test -z "${REASON}" && REASON="Expiring $$ on ${EXPDIR}"
196         EXPIREFLAGS="${EXPIREFLAGS} '-d${EXPDIR}' '-r${REASON}'"
197 }
198
199 test -n "${RMFILE}" && {
200         if ${DOGROUPBASEEXPIRY} ; then
201             EXPIREOVERFLAGS="${EXPIREOVERFLAGS} -z${RMFILE}"
202         else
203             EXPIREFLAGS="${EXPIREFLAGS} -z${RMFILE}"
204         fi
205     }
206
207 test -n "${LOWMARKFILE}" && {
208         EXPIREOVERFLAGS="${EXPIREOVERFLAGS} -Z${LOWMARKFILE}"
209 }
210
211
212 if ${DOMAIL} ; then
213     ##  Try to get a temporary file.
214     TEMP=${TMPDIR}/doex$$
215     test -f ${TEMP} && {
216         echo "Temporary file ${TEMP} exists" | eval ${MAIL}
217         exit 1
218     }
219     touch ${TEMP}
220     chmod 0660 ${TEMP}
221     exec 3>&1 >${TEMP} 2>&1
222 fi
223
224 cd ${PATHETC}
225
226 ##  Show the status of the news system.
227 ${DOSTAT} && {
228     ${INNSTAT}
229     echo ''
230 }
231
232 ##  Lock out others.
233 trap 'rm -f ${LOCK} ; exit 1' 1 2 3 15
234 shlock -p $$ -f ${LOCK} || {
235     ( echo "$0: Locked by `cat ${LOCK}`"; ${INNSTAT} ) | eval ${MAIL}
236     exit 1
237 }
238
239 ##  Run any user programs.
240 if [ -n "${PROGRAMS}" ] ; then
241     for P in ${PROGRAMS} ; do
242         echo ''
243         echo "${P}:"
244         eval ${P}
245     done
246 fi
247
248 ${DOLOGS} && {
249     echo ''
250     scanlogs ${SCANARG}
251 }
252
253 # group-based expiry (delete expired overview first)
254 if [ ${DOGROUPBASEEXPIRY} = true -a ${DOEXPIREOVER} = true ] ; then
255     if ${DOEXPLOG}; then
256         echo "${EXPIREOVER} start `date`: (${EXPIREOVERFLAGS})" >>${EXPLOG}
257     fi
258     ( cd ${HISTDIR} ; exec 2>&1 ; eval ${EXPIREOVER} "${EXPIREOVERFLAGS}" ) \
259         >>${EXPLOG}
260     if ${DOEXPLOG}; then
261         echo "${EXPIREOVER} end `date`" >>${EXPLOG}
262     fi
263     test -n "${LOWMARKFILE}" && {
264         echo "lowmarkrenumber begin `date`: (${LOWMARKFILE})"   >>${EXPLOG}
265         ctlinnd -s -t`wc -l <${ACTIVE}` lowmark ${LOWMARKFILE} 2>&1
266         echo "lowmarkrenumber end `date`"                       >>${EXPLOG}
267         rm -f ${MOST_LOGS}/expire.lastlowmark
268         mv ${LOWMARKFILE} ${MOST_LOGS}/expire.lastlowmark
269     }
270     test -n "${RMFILE}" -a -s "${RMFILE}" && {
271         mv ${RMFILE} ${RMFILE}.$$ && RMFILE=${RMFILE}.$$
272
273         test -n "${TMPDIR}" && SORT="${SORT} -T ${TMPDIR}"      
274         ${SORT} -u -o ${RMFILE} ${RMFILE}
275         if ${DOEXPLOG}; then
276             echo "      expirerm start `date`" >>${EXPLOG}
277         fi
278         expirerm ${RMFILE}
279         if ${DOEXPLOG}; then
280             echo "      expirerm end `date`" >>${EXPLOG}
281         fi
282     }
283     DOEXPIREOVER=false
284 fi
285
286 ##  The heart of the matter:  prologs, expire, epilogs.
287 if ${DOEXPIRE} ; then
288
289     ## Wait to be fairly certain innwatch is not in the middle of a pass
290     ## Since we're locked, innwatch will pause now till we're done
291     sleep 30
292
293     ##  See if we're throttled for lack of space.
294     SERVERMODE=`ctlinnd -t $TOUT mode 2>/dev/null | ${SED} 1q`
295     case "${SERVERMODE}" in
296     'Server paused'*'[innwatch:'*)
297         ## If paused, by innwatch, then turn pause into throttle
298         ## as we're going to stay that way for a while now
299         ctlinnd -t $TOUT -s throttle \
300             "`expr \"${SERVERMODE}\" : 'Server paused \(.*\)'`" || {
301             ( echo "$0: Cannot throttle while innwatch paused";
302               ${INNSTAT} ) | eval ${MAIL}
303             exit 1
304         }
305     esac
306     case "${SERVERMODE}" in
307     *space*" -- throttling")
308         echo "${SERVERMODE} -- trying to recover"
309         THROTTLED=true
310         EXPIREFLAGS="${EXPIREFLAGS} -n"
311         MESSAGE=
312         ;;
313     *"[innwatch:"*)
314         echo "${SERVERMODE} -- pressing on"
315         THROTTLED=false
316         EXPIREFLAGS="${EXPIREFLAGS} -n"
317         MESSAGE=
318         DORENUMBER=false
319         ;;
320     *)
321         THROTTLED=false
322         ;;
323     esac
324
325     ##  Throttle server if we need to.
326     if [ -n "${MESSAGE}" ] ; then
327         ctlinnd -t $TOUT -s -t120 throttle "${MESSAGE}" 2>&1 || {
328             ( echo "$0: Cannot throttle news"; ${INNSTAT} ) | eval ${MAIL}
329             exit 1
330         }
331     fi
332
333     #
334     #  Get rid of an old expire RMFILE since news.daily locks itself and
335     #  we would not get here if another instance were still running.
336     #        
337     if [ -n "${RMFILE}" ] ; then
338         rm -f ${RMFILE}
339     fi
340
341     ##  Actual expire the articles (finally!).
342     test -n "${EXPIRECTL}" && EXPIREFLAGS="${EXPIREFLAGS} ${EXPIRECTL}"
343     if ${DOEXPLOG}; then
344         echo "expire begin `date`: (${EXPIREFLAGS})"            >>${EXPLOG}
345         ( cd ${HISTDIR}; exec 2>&1 ; eval expire "${EXPIREFLAGS}" ) \
346             | ${SED} -e '/No such file or directory/d' \
347                      -e 's/^/    /' >>${EXPLOG}
348         echo "expire end `date`"                                >>${EXPLOG}
349     else
350         eval expire "${EXPIREFLAGS}" 2>&1 | grep -v 'No such file or directory'
351     fi
352
353     ##  If built on another filesystem, move history files.
354     if [ -n "${EXPDIR}" ] ; then
355         if [ ! -f ${EXPDIR}/history.n -o ! -f ${EXPDIR}/history.n.done ] ; then
356             ( echo "$0: No new history files"; ${INNSTAT} ) | eval ${MAIL}
357             exit 1
358         fi
359         cp /dev/null ${HISTORY}
360         mv -f ${EXPDIR}/history.n ${HISTORY}
361         mv -f ${EXPDIR}/history.n.dir ${HISTORY}.dir
362         if [ X${TAGGEDHASH} = XDO ] ; then
363             mv -f ${EXPDIR}/history.n.pag ${HISTORY}.pag
364         else
365             mv -f ${EXPDIR}/history.n.index ${HISTORY}.index
366             mv -f ${EXPDIR}/history.n.hash ${HISTORY}.hash
367         fi
368         rm -f ${EXPDIR}/history.n.done
369
370         case "${EXPIREFLAGS}" in
371         *-n*)
372             ;;
373         *)
374             MESSAGE="${REASON}"
375             ;;
376         esac
377     fi
378
379     ##  Restart the server if we need to.
380     if ${THROTTLED} || test -n "${MESSAGE}" ; then
381         ctlinnd -t "$TOUT" -s go "${MESSAGE}" 2>&1 || {
382             ( echo "$0: Cannot unthrottle news"; ${INNSTAT} ) | eval ${MAIL}
383             exit 1
384         }
385     fi
386     if ${DOEXPLOG}; then
387         echo "  all done `date`" >>${EXPLOG}
388     fi
389 fi
390
391 ##  Remove old sockets.
392 ${DORM} &&
393     find ${TEMPSOCKDIR} -name "${TEMPSOCK}" -mtime +2 -exec rm -f '{}' ';'
394
395 ##  Did we became throttled during the run?
396 SERVERMODE=`ctlinnd mode 2>/dev/null | ${SED} 1q`
397 case "${SERVERMODE}" in
398 *space*" -- throttling")
399     ##  We did, try to unthrottle the server.
400     echo "${SERVERMODE} -- trying to recover"    
401     ctlinnd -s go ""
402     ;;
403 esac
404
405 ##  Release the lock now, everything below this must be able to withstand
406 ##  simultaneous news.daily's running.   We do this so innwatch can start
407 ##  monitoring again asap after the expire is done -- removing the
408 ##  articles isn't critical, nor is the renumber.
409 rm ${LOCK}
410
411 ## Remove the articles that are supposed to go
412 if [ ${DOEXPIRE} = true -a ${DOGROUPBASEEXPIRY} != true ] ; then
413     test -n "${RMFILE}" -a -s "${RMFILE}" && {
414         mv ${RMFILE} ${RMFILE}.$$ && RMFILE=${RMFILE}.$$
415
416         test -n "${TMPDIR}" && SORT="${SORT} -T ${TMPDIR}"      
417         ${SORT} -u -o ${RMFILE} ${RMFILE}
418         if ${DOEXPLOG}; then
419             echo "      expirerm start `date`" >>${EXPLOG}
420         fi
421         expirerm ${RMFILE}
422         if ${DOEXPLOG}; then
423             echo "      expirerm end `date`" >>${EXPLOG}
424         fi
425         ${DOEXPIREOVER} && {
426             if ${DOEXPLOG}; then
427                 echo "  ${EXPIREOVER} start `date`" >>${EXPLOG}
428             fi
429             ( cd ${HISTDIR} ; eval ${EXPIREOVER} "${EXPIREOVERFLAGS}" 2>&1 ) | \
430               grep -v 'No such file or directory'
431             DOEXPIREOVER=false
432             if ${DOEXPLOG}; then
433                 echo "  ${EXPIREOVER} end `date`" >>${EXPLOG}
434             fi
435         }
436         test -n "${LOWMARKFILE}" && {
437             echo "lowmarkrenumber begin `date`: (${LOWMARKFILE})"   >>${EXPLOG}
438             ctlinnd -s -t`wc -l <${ACTIVE}` lowmark ${LOWMARKFILE} 2>&1
439             echo "lowmarkrenumber end `date`"                       >>${EXPLOG}
440             rm -f ${MOST_LOGS}/expire.lastlowmark
441             mv ${LOWMARKFILE} ${MOST_LOGS}/expire.lastlowmark
442         }
443     }
444     # expire overview lines for files we just removed
445     if ${DOEXPIREOVER}; then
446         if ${DOEXPLOG}; then
447             echo "      ${EXPIREOVER} start `date`" >>${EXPLOG}
448         fi
449         ( cd ${HISTDIR} ; eval ${EXPIREOVER} "${EXPIREOVERFLAGS}" 2>&1 ) | \
450             grep -v 'No such file or directory'
451         DOEXPIREOVER=false
452         if ${DOEXPLOG}; then
453             echo "      ${EXPIREOVER} end `date`" >>${EXPLOG}
454         fi
455         test -n "${LOWMARKFILE}" && {
456             echo "lowmarkrenumber begin `date`: (${LOWMARKFILE})"   >>${EXPLOG}
457             ctlinnd -s -t`wc -l <${ACTIVE}` lowmark ${LOWMARKFILE} 2>&1
458             echo "lowmarkrenumber end `date`"                       >>${EXPLOG}
459             rm -f ${MOST_LOGS}/expire.lastlowmark
460             mv ${LOWMARKFILE} ${MOST_LOGS}/expire.lastlowmark
461         }
462     fi
463 fi
464 # in case noexpire expireover
465 if ${DOEXPIREOVER}; then
466     if ${DOEXPLOG}; then
467         echo "  ${EXPIREOVER} start `date`" >>${EXPLOG}
468     fi
469     ( cd ${HISTDIR} ; eval ${EXPIREOVER} "${EXPIREOVERFLAGS}" 2>&1 ) | \
470         grep -v 'No such file or directory'
471     if ${DOEXPLOG}; then
472         echo "  ${EXPIREOVER} end `date`" >>${EXPLOG}
473     fi
474     test -n "${LOWMARKFILE}" && {
475         echo "lowmarkrenumber begin `date`: (${LOWMARKFILE})"   >>${EXPLOG}
476         ctlinnd -s -t`wc -l <${ACTIVE}` lowmark ${LOWMARKFILE} 2>&1
477         echo "lowmarkrenumber end `date`"                           >>${EXPLOG}
478         rm -f ${MOST_LOGS}/expire.lastlowmark
479         mv ${LOWMARKFILE} ${MOST_LOGS}/expire.lastlowmark
480     }
481 fi
482
483 ##  Renumber the active file.
484 if ${DORENUMBER} ; then
485     echo ''
486     echo 'Renumbering active file.'
487     if [ -z "${RENUMBER}" ] ;then
488         ctlinnd -s -t`wc -l <${ACTIVE}` renumber '' 2>&1
489     else
490         while read GROUP hi lo flag ; do
491             ctlinnd -s renumber ${GROUP} 2>&1
492             sleep ${RENUMBER}
493         done <${ACTIVE}
494     fi
495 fi
496
497 ##  Display expire log messages
498 if ${DOMAIL} ; then
499     if [ -s ${EXPLOG} ] ; then
500             echo Expire messages:
501             cat ${EXPLOG}
502             echo ---------
503             echo ''
504     fi
505 fi
506
507 ##  Show the status of the news system after expiration.
508 ${DOSTAT} && {
509     echo 'Post expiration status:' ; echo ''
510     ${INNSTAT}
511     echo ''
512 }
513
514 ##  Mail the report.
515 if ${DOMAIL} ; then
516     # Stop using the temp file, and mail captured output.
517     exec 1>&3 2>&1 3>&-
518     MAIL="${MAILCMD} -s \"${MAILSUBJ}\" ${NEWSMASTER}"
519     test -s ${TEMP} && cat ${TEMP} | ${SED} -e 's/^~/~~/' | eval ${MAIL}
520     rm -f ${TEMP}
521 fi
522
523 ##  Run any user programs.
524 if [ -n "${POSTPROGRAMS}" ] ; then
525     for P in ${POSTPROGRAMS} ; do
526         echo ''
527         echo "${P}:"
528         eval ${P}
529     done
530 fi
531
532 ##  All done
533 if ${DAILY} ; then
534     date >${PATHDB}/.news.daily
535 fi
536 ${RNEWS} -U
537 exit 0