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