aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/periodic/periodic.sh
blob: cdbd1b3b57fbf24fe95e57acbb88d65afc098e54 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/sh -
#
# $FreeBSD$
#
# Run nightly periodic scripts
#
# usage: periodic { daily | weekly | monthly | security } - run standard scripts
#        periodic /absolute/path/to/directory  - run periodic scripts in dir
#

usage () {
    echo "usage: $0 <directory of files to execute>" 1>&2
    echo "or     $0 { daily | weekly | monthly | security }"    1>&2
    exit 1
}

output_pipe()
{
    # Where's our output going ?
    eval output=\$${1##*/}_output
    case "$output" in
    /*) pipe="cat >>$output";;
    "") pipe=cat;;
    *)  pipe="mail -E -s '$host ${2}${2:+ }${1##*/} run output' $output";;
    esac
    eval $pipe
}

if [ $# -lt 1 ] ; then
    usage
fi

# Use a deterministic path to match the preset from /etc/crontab in case
# periodic is run interactively.
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin

# If possible, check the global system configuration file,
# to see if there are additional dirs to check
if [ -r /etc/defaults/periodic.conf ]; then
    . /etc/defaults/periodic.conf
    source_periodic_confs
fi

host=`hostname`
export host

# If we were called normally, then create a lock file for each argument
# in turn and reinvoke ourselves with the LOCKED argument.  This prevents
# very long running jobs from being overlapped by another run as this is
# will lead the system running progressivly slower and more and more jobs
# are run at once.
if [ $1 != "LOCKED" ]; then
    ret=0
    for arg; do
        lockfile=/var/run/periodic.${arg##*/}.lock
        lockf -s -t 0 "${lockfile}" /bin/sh $0 LOCKED "$arg"
        case $? in
        0) ;;
        73) #EX_CANTCREATE
            echo "can't create ${lockfile}" | \
                output_pipe $arg "$PERIODIC"
            ret=1
            ;;
        75) #EX_TEMPFAIL
            echo "$host ${arg##*/} prior run still in progress" | \
                output_pipe $arg "$PERIODIC"
            ret=1
            ;;
        *)
            ret=1
            ;;
        esac
    done
    exit $ret
fi

if [ $# -ne 2 ]; then
    usage
fi
shift
arg=$1

if [ -z "$PERIODIC_ANTICONGESTION_FILE" ] ; then
	export PERIODIC_ANTICONGESTION_FILE=`mktemp ${TMPDIR:-/tmp}/periodic.anticongestion.XXXXXXXXXX`
	remove_periodic_anticongestion_file=yes
else
	# We might be in a recursive invocation; let the top-level invocation
	# remove the file.
	remove_periodic_anticongestion_file=no
fi
if [ -t 0 ]; then
	export PERIODIC_IS_INTERACTIVE=1
fi
tmp_output=`mktemp ${TMPDIR:-/tmp}/periodic.XXXXXXXXXX`
context="$PERIODIC"
export PERIODIC="$arg${PERIODIC:+ }${PERIODIC}"

# Execute each executable file in the directory list.  If the x bit is not
# set, assume the user didn't really want us to muck with it (it's a
# README file or has been disabled).

success=YES info=YES badconfig=NO empty_output=YES	# Defaults when ${run}_* aren't YES/NO
for var in success info badconfig empty_output; do
    case $(eval echo "\$${arg##*/}_show_$var") in
    [Yy][Ee][Ss]) eval $var=YES;;
    [Nn][Oo])     eval $var=NO;;
    esac
done

case $arg in
/*) if [ -d "$arg" ]; then
        dirlist="$arg"
    else
        echo "$0: $arg not found" >&2
        exit 1
    fi
    ;;
*)  dirlist=
    for top in /etc/periodic ${local_periodic}; do
        [ -d $top/$arg ] && dirlist="$dirlist $top/$arg"
    done
    ;;
esac

{
    empty=TRUE
    processed=0
    for dir in $dirlist; do
        for file in $dir/*; do
            if [ -x $file -a ! -d $file ]; then
                output=TRUE
                processed=$(($processed + 1))
                $file </dev/null >$tmp_output 2>&1
                rc=$?
                if [ -s $tmp_output ]; then
                    case $rc in
                    0)  [ $success = NO ] && output=FALSE;;
                    1)  [ $info = NO ] && output=FALSE;;
                    2)  [ $badconfig = NO ] && output=FALSE;;
                    esac
                    [ $output = TRUE ] && { cat $tmp_output; empty=FALSE; }
                fi
                cp /dev/null $tmp_output
            fi
        done
    done
    if [ $empty = TRUE ]; then
        if [ $empty_output = TRUE ]; then
            [ $processed = 1 ] && plural= || plural=s
            echo "No output from the $processed file$plural processed"
        fi
    else
        echo ""
        echo "-- End of $arg output --"
    fi
} | output_pipe $arg "$context"

rm -f $tmp_output
if [ $remove_periodic_anticongestion_file = "yes" ] ; then
	rm -f $PERIODIC_ANTICONGESTION_FILE
fi