* Inotify support
authorDustin Kirkland <kirkland@canonical.com>
Thu, 5 Mar 2009 19:22:55 +0000 (13:22 -0600)
committerDustin Kirkland <kirkland@canonical.com>
Thu, 5 Mar 2009 19:22:55 +0000 (13:22 -0600)
    - big thanks for Jon Bernard <jbernard@librato.com> for all his help!
  * debian/dirs: add /etc/update-motd directory
  * debian/install: install /etc/update-motd/iwatch.xml
  * debian/iwatch.xml: iwatch configuration file
  * debian/update-motd.cron.d: use the "d" argument for the 10-minute job
  * update-motd:
    - default FREQ to "d"
    - default vars added for inotify
    - usage statement updated accordingly
    - ensure that the cronjobs are no-ops, if running in inotify mode
    - handle starting/stopping inotify via --enable and --disable
    - move the trap to the top, and make sure the lock is established
    - do not run the /etc/update-motd.*/ scripts, if in inotify mode
  * update-motd.1: documentation updated

debian/changelog
debian/dirs
debian/install
debian/iwatch.xml [new file with mode: 0644]
debian/update-motd.cron.d
update-motd
update-motd.1

index f0a3887..b748302 100644 (file)
@@ -1,3 +1,23 @@
+update-motd (1.12) jaunty; urgency=low
+
+  * Inotify support
+    - big thanks for Jon Bernard <jbernard@librato.com> for all his help!
+  * debian/dirs: add /etc/update-motd directory
+  * debian/install: install /etc/update-motd/iwatch.xml
+  * debian/iwatch.xml: iwatch configuration file
+  * debian/update-motd.cron.d: use the "d" argument for the 10-minute job
+  * update-motd:
+    - default FREQ to "d"
+    - default vars added for inotify
+    - usage statement updated accordingly
+    - ensure that the cronjobs are no-ops, if running in inotify mode
+    - handle starting/stopping inotify via --enable and --disable
+    - move the trap to the top, and make sure the lock is established
+    - do not run the /etc/update-motd.*/ scripts, if in inotify mode
+  * update-motd.1: documentation updated
+
+ -- Dustin Kirkland <kirkland@ubuntu.com>  Thu, 05 Mar 2009 13:20:14 -0600
+
 update-motd (1.11) jaunty; urgency=low
 
   * update-motd: don't fail the entire script, if renice/ionice fail,
index d88e04a..3ea7a2d 100644 (file)
@@ -1,4 +1,5 @@
 etc/cron.d
+etc/update-motd
 etc/update-motd.d
 etc/update-motd.d/hourly
 etc/update-motd.d/daily
index fb297f6..d6741ba 100644 (file)
@@ -1 +1,2 @@
 update-motd usr/sbin
+debian/iwatch.xml etc/update-motd/iwatch.xml
diff --git a/debian/iwatch.xml b/debian/iwatch.xml
new file mode 100644 (file)
index 0000000..8446b71
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
+
+<config>
+  <guard email="root@localhost" name="update-motd"/>
+  <watchlist>
+    <title>Message Of The Day</title>
+    <contactpoint email="root@localhost" name="Administrator"/>
+    <path type="single" syslog="on" exec="/usr/sbin/update-motd inotify">/var/run/update-motd</path>
+  </watchlist>
+</config>
index d1293dc..94299a3 100644 (file)
@@ -3,7 +3,7 @@
 # Running 'update-motd' dynamically generates the /etc/motd with
 # a concatenation of output from each script in /etc/update-motd.d/*
 
-*/10 * * * *   root    [ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd 2>/dev/null
+*/10 * * * *   root    [ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd 2>/dev/null
 0 * * * *      root    [ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd hourly 2>/dev/null
 0 0 * * *      root    [ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd daily 2>/dev/null
 0 0 * * 0      root    [ -x /usr/sbin/update-motd ] && /usr/sbin/update-motd weekly 2>/dev/null
index 7a4219b..5e73a65 100755 (executable)
@@ -32,10 +32,12 @@ NEW=/var/run/motd.new
 SKEL=/etc/motd.tail
 REAL=/var/run/motd
 DIR=/etc/$NAME.d
-FREQ=
+FREQ=d
 DISABLED=/var/lib/$NAME/disabled
 LASTRUN=/var/run/$NAME.lastrun
-FORCE=0
+INOTIFY_PID=/var/run/$NAME-inotify.pid
+INOTIFY_CONFIG=/etc/update-motd/iwatch.xml
+INOTIFY_DAEMON=/usr/bin/iwatch
 
 if [ -f "$NEW" ]; then
        # If /var/run/motd.new exists, another instance is running
@@ -43,17 +45,21 @@ if [ -f "$NEW" ]; then
        exit 0
 fi
 
+# Make sure we clean up the motd.new lock file if we exit for any reason
+touch "$NEW"
+trap "rm -f $NEW 2>/dev/null || true" EXIT HUP INT QUIT TERM
+
 usage() {
        echo "Usage:
 
   update-motd [--disable|--enable|--force] [d|hourly|daily|weekly|monthly]
 
     --disable - will prevent update-motd from running; useful for
-                temporarily disabling automatic updates of /etc/motd
-                by the /etc/cron.d/update-motd cronjob.
+                disabling automatic updates of /etc/motd by the
+               /etc/cron.d/update-motd cronjob or inotify daemon.
     --enable  - will allow update-motd to run; useful for enabling
                 automatic updates of /etc/motd through the
-                /etc/cron.d/update-motd cronjob.
+                /etc/cron.d/update-motd cronjob or inotify daemon.
     --force   - will override a disabled update-motd for a single
                 update of /etc/motd.
     d         - will run the scripts in /etc/$NAME.d        (Default)
@@ -61,42 +67,106 @@ usage() {
     daily     - will run the scripts in /etc/$NAME.d/daily
     weekly    - will run the scripts in /etc/$NAME.d/weekly
     monthly   - will run the scripts in /etc/$NAME.d/monthly
+    inotify   - will watch /var/run/$NAME, updating /etc/motd when a file
+                in that directory changes
 " 1>&2
 }
 
 FORCE=0
+INOTIFY=0
+DISABLE=0
+ENABLE=0
 for arg in $@; do
        case $arg in
                "--disable"|"-d")
-                       touch "$DISABLED"
-                       echo "$NAME is now disabled." 1>&2
-                       # Regenerate motd created at boot by
-                       # /etc/init.d/bootmisc.sh
-                       uname -snrvm > $REAL
-                       [ -f $SKEL ] && cat $SKEL >> $REAL
-                       exit 0
+                       DISABLE=1
                ;;
                "--enable"|"-e")
-                       rm -f "$DISABLED"
-                       echo "$NAME is now enabled." 1>&2
-                       # Do not exit here, as we want to update the MOTD
-                       # immediately upon enabling
+                       ENABLE=1
                ;;
                "--force"|"-f")
                        FORCE=1
                ;;
-               "d")
-                       FREQ=
-               ;;
-               "hourly"|"daily"|"weekly"|"monthly")
+               "d"|"hourly"|"daily"|"weekly"|"monthly")
                        FREQ=$arg
                ;;
+               "inotify")
+                       if [ ! -x "/usr/bin/iwatch" ]; then
+                               echo "The program 'iwatch' is currently not installed.  You can install it by typing:" 1>&2
+                               echo "sudo apt-get install iwatch" 1>&2
+                               exit 1
+                       fi
+                       INOTIFY=1
+                       FREQ=
+               ;;
                *)
                        usage
                        exit 1
                ;;
        esac
 done
+
+case "$FREQ" in
+       "d"|"hourly"|"daily"|"weekly"|"monthly")
+               if [ -n "$FREQ" -a -r "$INOTIFY_PID" -a "$DISABLE" = "0" -a "$ENABLE" = "0" ]; then
+                       if ps `cat $INOTIFY_PID` >/dev/null 2>&1; then
+                               # We're running in inotify mode, so exit immediately
+                               # This no-ops the cron jobs!
+                               exit 0
+                       fi
+               fi
+       ;;
+       *)
+       ;;
+esac
+[ "$FREQ" = "d" ] && FREQ=
+
+if [ "$DISABLE" = "1" ]; then
+       if [ "$INOTIFY" = "1" ]; then
+               if [ -f "$INOTIFY_PID" ]; then
+                       start-stop-daemon -K -p "$INOTIFY_PID"
+                       echo "$NAME inotify daemon now stopped." 1>&2
+                       rm -f "$INOTIFY_PID"
+               else
+                       echo "$NAME inotify daemon not found." 1>&2
+                       exit 1
+               fi
+       else
+               touch "$DISABLED" && echo "$NAME is now disabled." 1>&2
+               rc=$?
+       fi
+       # Regenerate motd created at boot by /etc/init.d/bootmisc.sh
+       uname -snrvm > $REAL
+       [ -f $SKEL ] && cat $SKEL >> $REAL
+       exit $rc
+fi
+
+if [ "$ENABLE" = "1" ]; then
+       rm -f "$DISABLED"
+       echo "$NAME is now enabled." 1>&2
+       # Do not exit here, as we want to update the MOTD
+       # immediately upon enabling
+       if [ "$INOTIFY" = "1" ]; then
+               if [ -f "$INOTIFY_PID" ]; then
+                       echo "$NAME inotify daemon already running" 1>&2
+                       exit 1
+               else
+                       if [ ! -r "$INOTIFY_CONFIG" ]; then
+                               echo "Error reading config file: $INOTIFY_CONFIG" 2>&1
+                               exit 1
+                       fi
+                       if $INOTIFY_DAEMON -d -f $INOTIFY_CONFIG -p $INOTIFY_PID; then
+                               echo "$NAME inotify daemon started." 1>&2
+                       else
+                               rc=$?
+                               echo "Error starting $NAME inotify daemon." 1>&2
+                               exit $rc
+
+                       fi
+               fi
+       fi
+fi
+
 DIR="$DIR/$FREQ"
 
 if [ -f "$DISABLED" ] && [ "$FORCE" != "1" ]; then
@@ -107,9 +177,6 @@ You might try:
        exit 1
 fi
 
-# Make sure we clean up the motd.new lock file if we exit for any reason
-trap "rm -f $NEW 2>/dev/null || true" EXIT HUP INT QUIT TERM
-
 if [ "$FORCE" != "1" ]; then
        # Be *really* nice, if we're running in the background (not forced)
        # But don't fail the script if we're not able to 'nice'
@@ -126,14 +193,19 @@ uname -snrvm > $NEW
 # Create a directory to cache the script output across update-motd
 # runs of different frequencies
 mkdir -p "/var/run/$NAME"
-# Obtain a list of the current scripts "due" to run
-scripts=`run-parts --lsbsysinit --test $DIR`
-for script in $scripts; do
-       file=`basename "$script"`
-       # Run each script, writing to a cache file, of the same num-name
-       # of the script executing
-       $script > "/var/run/$NAME/$file" 2>/dev/null
-done
+
+# If we're not in inotify-mode, run each script
+if [ "$INOTIFY" = "0" ]; then
+       # Obtain a list of the current scripts "due" to run
+       scripts=`run-parts --lsbsysinit --test $DIR`
+       for script in $scripts; do
+               file=`basename "$script"`
+               # Run each script, writing to a cache file, of the same num-name
+               # of the script executing
+               $script > "/var/run/$NAME/$file" 2>/dev/null
+       done
+fi
+
 # Now, concatenate ALL of the cached update-motd output, thus collecting
 # ordered output across update-motd runs of different frequencies
 for file in `ls /var/run/$NAME`; do
index 55ec0c3..ddd70c7 100644 (file)
@@ -1,21 +1,22 @@
 .IX Title "UPDATE-MOTD 1"
-.TH UPDATE-MOTD 1 "2008-11-11" update-motd update-motd
+.TH UPDATE-MOTD 1 "2009-03-05" update-motd update-motd
 
 .SH "NAME"
 update\-motd \- Automatically update the message-of-the-day (MOTD)
 
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
-update\-motd [\-\-disable|\-\-enable|\-\-force] [d|hourly|daily|weekly|monthly]
+update\-motd [\-\-disable|\-\-enable|\-\-force]
+            [d|hourly|daily|weekly|monthly|inotify]
 
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .TP
 \fB\-\-disable\fP
-Prevent update-motd from running. This is useful for temporarily disabling automatic updates of \fI/etc/motd\fP by the \fI/etc/cron.d/update-motd\fP cronjob.  Note that this regenerates a base MOTD without the update-motd additions, and then exits.
+Prevent update-motd from running. This is useful for temporarily disabling automatic updates of \fI/etc/motd\fP by the \fI/etc/cron.d/update-motd\fP cronjob or the inotify daemon.  Note that this regenerates a base MOTD without the update-motd additions, and then exits.
 .TP
 \fB\-\-enable\fP
-Allow update-motd to run.  This is useful for enabling automatic updates of \fI/etc/motd\fP through the \fI/etc/cron.d/update-motd\fP cronjob.  Note that this updates the MOTD immediately.
+Allow update-motd to run.  This is useful for enabling automatic updates of \fI/etc/motd\fP through the \fI/etc/cron.d/update-motd\fP cronjob or inotify daemon.  Note that this updates the MOTD immediately.
 .TP
 \fB\-\-force\fP
 Override a disabled update-motd for a single, immediate update of \fI/etc/motd\fP.
@@ -34,11 +35,20 @@ Runs the scripts in /etc/update-motd.d/weekly
 .TP
 \fBmonthly\fP
 Runs the scripts in /etc/update-motd.d/monthly
+.TP
+\fBinotify\fP
+Watches /var/run/$NAME, updating /etc/motd when a file in that directory changes
+
 
 
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
-This script executes lists of scripts in lexical order, concatenating and writing the output to \fI/var/lib/motd\fP, which is usually a symbolic link to \fI/etc/motd\fP.
+
+\fBcron mode\fP
+
+By default, \fBupdate-motd\fP is executed by a series of cronjobs at specific intervals (every 10 minutes, hourly, daily, weekly, monthly).
+
+It executes lists of scripts in lexical order, concatenating and writing the output to \fI/var/lib/motd\fP, which is usually a symbolic link to \fI/etc/motd\fP.
 
 Users and/or packages should add symbolic links to \fI/etc/update-motd.d/\fP, \fI/etc/update-motd.d/hourly\fP, \fI/etc/update-motd.d/daily\fP, \fI/etc/update-motd.d/weekly\fP, \fI/etc/update-motd.d/monthly\fP, prepended with a two-digit number to define the displayed order, as obeyed by \fBrun-parts(8)\fP.
 
@@ -50,8 +60,18 @@ The update-motd script will not execute if the file \fI/var/lib/update-motd/disa
 
 If enabled, timestamp of the last \fBupdate-motd\fP run will be written to \fI/var/run/update-motd.lastrun\fP.
 
+\fBinotify mode\fP
+
+Alternatively, \fBupdate-motd\fP can execute in an inotify mode, using \fBiwatch\fP.  In this case, update-motd will 'watch' the \fI/var/run/update-motd\fP directory for changes of any kind and trigger an update of \fI/etc/motd\fP.
+
+To start and stop \fBupdate-motd\fP in inotify-mode, ensure that you have the \fBiwatch\fP package installed, and run:
+   $ sudo update-motd --enable inotify
+   $ sudo update-motd --disable inotify
+
+In this mode, scripts in \fI/etc/update-motd.*/\fP will not be executed at their regular intervals by the cron job.  Rather, it is the responsibility of various applications to write data to \fI/var/run/update-motd\fP, and \fBupdate-motd\fP merely picks it up and inserts into the \fI/etc/motd\fP.
+
 .SH FILES
-\fI/etc/cron.d/update-motd\fP, \fI/etc/update-motd.d/\fP, \fI/etc/update-motd.d/hourly\fP, \fI/etc/update-motd.d/daily\fP, \fI/etc/update-motd.d/weekly\fP, \fI/etc/update-motd.d/monthly\fP, \fI/etc/motd.tail\fP, \fI/var/run/motd\fP, \fI/var/lib/update-motd/disabled\fP, \fI/var/run/update-motd\fP, \fI/var/run/update-motd.lastrun\fP
+\fI/etc/cron.d/update-motd\fP, \fI/etc/update-motd.d/\fP, \fI/etc/update-motd.d/hourly\fP, \fI/etc/update-motd.d/daily\fP, \fI/etc/update-motd.d/weekly\fP, \fI/etc/update-motd.d/monthly\fP, \fI/etc/motd.tail\fP, \fI/etc/update-motd/iwatch.xml\fP, \fI/var/run/motd\fP, \fI/var/lib/update-motd/disabled\fP, \fI/var/run/update-motd\fP, \fI/var/run/update-motd.lastrun\fP
 
 .SH "AUTHOR"
 .IX Header "AUTHOR"