Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Feb 2012 23:18:05 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r231568 - head/usr.sbin/periodic
Message-ID:  <201202122318.q1CNI5YQ005365@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Sun Feb 12 23:18:05 2012
New Revision: 231568
URL: http://svn.freebsd.org/changeset/base/231568

Log:
  Prevent periodic scripts that run longer than the expected period from
  starting up before the previous script finishes.  This prevents an
  infinite number of them from piling up and slowing a system down.
  
  Since all the refactoring to make this happen required churning the
  indenting of most of this file, make the indentation more consistent.
  
  Reviewed by:	simon
  MFC after:	1 week

Modified:
  head/usr.sbin/periodic/periodic.sh

Modified: head/usr.sbin/periodic/periodic.sh
==============================================================================
--- head/usr.sbin/periodic/periodic.sh	Sun Feb 12 23:12:47 2012	(r231567)
+++ head/usr.sbin/periodic/periodic.sh	Sun Feb 12 23:18:05 2012	(r231568)
@@ -14,6 +14,18 @@ usage () {
     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 ${1##*/} run output' $output";;
+    esac
+    eval $pipe
+}
+
 if [ $# -lt 1 ] ; then
     usage
 fi
@@ -27,83 +39,102 @@ 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 -t 0 "${lockfile}" /bin/sh $0 LOCKED "$arg"
+        case $? in
+        0) ;;
+        73) #EX_CANTCREATE
+            echo "can't create ${lockfile}" | output_pipe $arg
+            ret=1
+            ;;
+        75) #EX_TEMPFAIL
+            echo "$host ${arg##*/} prior run still in progress" | \
+                output_pipe $arg
+            ret=1
+            ;;
+        *)
+            ret=1
+            ;;
+        esac
+    done
+    exit $ret
+fi
+
+if [ $# -ne 2 ]; then
+    usage
+fi
+shift
+arg=$1
+
 tmp_output=`mktemp ${TMPDIR:-/tmp}/periodic.XXXXXXXXXX`
 
 # 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).
 
-for arg
-do
-    # Where's our output going ?
-    eval output=\$${arg##*/}_output
-    case "$output" in
-    /*) pipe="cat >>$output";;
-    "") pipe=cat;;
-    *)  pipe="mail -E -s '$host ${arg##*/} run output' $output";;
+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
 
-    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
+case $arg in
+/*) if [ -d "$arg" ]; then
+        dirlist="$arg"
+    else
+        echo "$0: $arg not found" >&2 
+        continue
+    fi
+    ;;
+*)  dirlist=
+    for top in /etc/periodic ${local_periodic}; do
+        [ -d $top/$arg ] && dirlist="$dirlist $top/$arg"
     done
+    ;;
+esac
 
-    case $arg in
-    /*) if [ -d "$arg" ]
-        then
-            dirlist="$arg"
-        else
-            echo "$0: $arg not found" >&2 
-            continue
-        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
+{
+    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
-            done
+                cp /dev/null $tmp_output
+            fi
         done
-        if [ $empty = TRUE ]
-        then
-          if [ $empty_output = TRUE ]
-          then
+    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
-    } | eval $pipe
-done
+    else
+        echo ""
+        echo "-- End of $arg output --"
+    fi
+} | output_pipe ${arg}
+
 rm -f $tmp_output



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202122318.q1CNI5YQ005365>