xref: /freebsd/usr.sbin/periodic/periodic.sh (revision c8b89c11a1181e900acb638cfde7a55e92553175)
1#!/bin/sh -
2#
3#
4# Run nightly periodic scripts
5#
6# usage: periodic { daily | weekly | monthly | security } - run standard scripts
7#        periodic /absolute/path/to/directory  - run periodic scripts in dir
8#
9
10usage () {
11    echo "usage: $0 <directory of files to execute>" 1>&2
12    echo "or     $0 { daily | weekly | monthly | security }"    1>&2
13    exit 1
14}
15
16output_pipe()
17{
18    # Where's our output going ?
19    eval output=\$${1##*/}_output
20    case "$output" in
21    /*) pipe="cat >>$output";;
22    "") pipe=cat;;
23    *)  pipe="mail -E -s '$host ${2}${2:+ }${1##*/} run output' $output";;
24    esac
25    eval $pipe
26}
27
28if [ $# -lt 1 ] ; then
29    usage
30fi
31
32# If possible, check the global system configuration file,
33# to see if there are additional dirs to check
34if [ -r /etc/defaults/periodic.conf ]; then
35    . /etc/defaults/periodic.conf
36    source_periodic_confs
37fi
38
39# Use a deterministic path to match the preset from /etc/crontab in case
40# periodic is run interactively.
41export PATH=/sbin:/bin:/usr/sbin:/usr/bin:${_localbase}/sbin:${_localbase}/bin
42
43host=`hostname`
44export host
45
46# If we were called normally, then create a lock file for each argument
47# in turn and reinvoke ourselves with the LOCKED argument.  This prevents
48# very long running jobs from being overlapped by another run as this is
49# will lead the system running progressively slower and more and more jobs
50# are run at once.
51if [ $1 != "LOCKED" ]; then
52    ret=0
53    for arg; do
54        lockfile=/var/run/periodic.${arg##*/}.lock
55        lockf -s -t 0 "${lockfile}" /bin/sh $0 LOCKED "$arg"
56        case $? in
57        0) ;;
58        73) #EX_CANTCREATE
59            echo "can't create ${lockfile}" | \
60                output_pipe $arg "$PERIODIC"
61            ret=1
62            ;;
63        75) #EX_TEMPFAIL
64            echo "$host ${arg##*/} prior run still in progress" | \
65                output_pipe $arg "$PERIODIC"
66            ret=1
67            ;;
68        *)
69            ret=1
70            ;;
71        esac
72    done
73    exit $ret
74fi
75
76if [ $# -ne 2 ]; then
77    usage
78fi
79shift
80arg=$1
81
82if [ -z "$PERIODIC_ANTICONGESTION_FILE" ] ; then
83	export PERIODIC_ANTICONGESTION_FILE=`mktemp ${TMPDIR:-/tmp}/periodic.anticongestion.XXXXXXXXXX`
84	remove_periodic_anticongestion_file=yes
85else
86	# We might be in a recursive invocation; let the top-level invocation
87	# remove the file.
88	remove_periodic_anticongestion_file=no
89fi
90if [ -t 0 ]; then
91	export PERIODIC_IS_INTERACTIVE=1
92fi
93tmp_output=`mktemp ${TMPDIR:-/tmp}/periodic.XXXXXXXXXX`
94context="$PERIODIC"
95export PERIODIC="$arg${PERIODIC:+ }${PERIODIC}"
96
97# Execute each executable file in the directory list.  If the x bit is not
98# set, assume the user didn't really want us to muck with it (it's a
99# README file or has been disabled).
100
101success=YES info=YES badconfig=NO empty_output=YES	# Defaults when ${run}_* aren't YES/NO
102for var in success info badconfig empty_output; do
103    case $(eval echo "\$${arg##*/}_show_$var") in
104    [Yy][Ee][Ss]) eval $var=YES;;
105    [Nn][Oo])     eval $var=NO;;
106    esac
107done
108
109case $arg in
110/*) if [ -d "$arg" ]; then
111        dirlist="$arg"
112    else
113        echo "$0: $arg not found" >&2
114        exit 1
115    fi
116    ;;
117*)  dirlist=
118    for top in /etc/periodic ${local_periodic}; do
119        [ -d $top/$arg ] && dirlist="$dirlist $top/$arg"
120    done
121    ;;
122esac
123
124{
125    empty=TRUE
126    processed=0
127    for dir in $dirlist; do
128        for file in $dir/*; do
129            if [ -x $file -a ! -d $file ]; then
130                output=TRUE
131                processed=$(($processed + 1))
132                $file </dev/null >$tmp_output 2>&1
133                rc=$?
134                if [ -s $tmp_output ]; then
135                    case $rc in
136                    0)  [ $success = NO ] && output=FALSE;;
137                    1)  [ $info = NO ] && output=FALSE;;
138                    2)  [ $badconfig = NO ] && output=FALSE;;
139                    esac
140                    [ $output = TRUE ] && { cat $tmp_output; empty=FALSE; }
141                fi
142                cp /dev/null $tmp_output
143            fi
144        done
145    done
146    if [ $empty = TRUE ]; then
147        if [ $empty_output = TRUE ]; then
148            [ $processed = 1 ] && plural= || plural=s
149            echo "No output from the $processed file$plural processed"
150        fi
151    else
152        echo ""
153        echo "-- End of $arg output --"
154    fi
155} | output_pipe $arg "$context"
156
157rm -f $tmp_output
158if [ $remove_periodic_anticongestion_file = "yes" ] ; then
159	rm -f $PERIODIC_ANTICONGESTION_FILE
160fi
161