#!/bin/sh - # # $FreeBSD: stable/11/usr.sbin/periodic/periodic.sh 321259 2017-07-20 00:33:04Z ngie $ # # Run nightly periodic scripts # # usage: periodic { daily | weekly | monthly | security } - run standard scripts # periodic /absolute/path/to/directory - run periodic scripts in dir # proc usage { echo "usage: $0 " !1 > !2 echo "or $0 { daily | weekly | monthly | security }" !1 > !2 exit 1 } proc output_pipe { # Where's our output going ? eval output='$'$(1##*/)_output match $output { with /* setglobal pipe = ""cat >>$output"" with "" setglobal pipe = 'cat' with * setglobal pipe = ""mail -E -s '$host $(2)$(2:+ )$(1##*/) run output' $output"" } eval $pipe } if test $Argc -lt 1 { usage } # If possible, check the global system configuration file, # to see if there are additional dirs to check if test -r /etc/defaults/periodic.conf { source /etc/defaults/periodic.conf source_periodic_confs } setglobal 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 test $1 != "LOCKED" { setglobal ret = '0'for arg in @Argv { setglobal lockfile = "/var/run/periodic.$(arg##*/).lock" lockf -t 0 $(lockfile) /bin/sh $0 LOCKED $arg match $Status { with 0 with 73 #EX_CANTCREATE echo "can't create $(lockfile)" | \ output_pipe $arg $PERIODIC setglobal ret = '1' with 75 #EX_TEMPFAIL echo "$host $(arg##*/) prior run still in progress" | \ output_pipe $arg $PERIODIC setglobal ret = '1' with * setglobal ret = '1' } } exit $ret } if test $Argc -ne 2 { usage } shift setglobal arg = $1 if test -z $PERIODIC_ANTICONGESTION_FILE { export PERIODIC_ANTICONGESTION_FILE=$[mktemp $(TMPDIR:-/tmp)/periodic.anticongestion.XXXXXXXXXX] } if tty > /dev/null !2 > !1 { export PERIODIC_IS_INTERACTIVE=1 } setglobal tmp_output = $[mktemp $(TMPDIR:-/tmp)/periodic.XXXXXXXXXX] setglobal 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). setglobal success = 'YES', info = 'YES', badconfig = 'NO', empty_output = 'YES' # Defaults when ${run}_* aren't YES/NO for var in [success info badconfig empty_output] { match $[eval echo "\$$(arg##*/)_show_$var] { with [Yy][Ee][Ss] eval $var=YES with [Nn][Oo] eval $var=NO } } match $arg { with /* if test -d $arg { setglobal dirlist = $arg } else { echo "$0: $arg not found" > !2 continue } with * setglobal dirlist = '' for top in [/etc/periodic $(local_periodic)] { test -d $top/$arg && setglobal dirlist = ""$dirlist $top/$arg"" } } do { setglobal empty = 'TRUE' setglobal processed = '0' for dir in [$dirlist] { for file in [$dir/*] { if test -x $file -a ! -d $file { setglobal output = 'TRUE' setglobal processed = $shExpr('$processed + 1') $file $tmp_output !2 > !1 setglobal rc = $Status if test -s $tmp_output { match $rc { with 0 test $success = NO && setglobal output = 'FALSE' with 1 test $info = NO && setglobal output = 'FALSE' with 2 test $badconfig = NO && setglobal output = 'FALSE' } test $output = TRUE && do { cat $tmp_output; setglobal empty = 'FALSE'; } } cp /dev/null $tmp_output } } } if test $empty = TRUE { if test $empty_output = TRUE { test $processed = 1 && setglobal plural = '' || setglobal plural = 's' echo "No output from the $processed file$plural processed" } } else { echo "" echo "-- End of $arg output --" } } | output_pipe $arg $context rm -f $tmp_output rm -f $PERIODIC_ANTICONGESTION_FILE