From: Dustin Kirkland Date: Thu, 5 Mar 2009 19:22:55 +0000 (-0600) Subject: * Inotify support X-Git-Url: http://git.etc.gen.nz/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=201c8045d1b75fa5adc92144859c88ac8705163f;p=update-motd.git * Inotify support - big thanks for Jon Bernard 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 --- diff --git a/debian/changelog b/debian/changelog index f0a3887..b748302 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,23 @@ +update-motd (1.12) jaunty; urgency=low + + * Inotify support + - big thanks for Jon Bernard 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 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, diff --git a/debian/dirs b/debian/dirs index d88e04a..3ea7a2d 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,4 +1,5 @@ etc/cron.d +etc/update-motd etc/update-motd.d etc/update-motd.d/hourly etc/update-motd.d/daily diff --git a/debian/install b/debian/install index fb297f6..d6741ba 100644 --- a/debian/install +++ b/debian/install @@ -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 index 0000000..8446b71 --- /dev/null +++ b/debian/iwatch.xml @@ -0,0 +1,11 @@ + + + + + + + Message Of The Day + + /var/run/update-motd + + diff --git a/debian/update-motd.cron.d b/debian/update-motd.cron.d index d1293dc..94299a3 100644 --- a/debian/update-motd.cron.d +++ b/debian/update-motd.cron.d @@ -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 d 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 diff --git a/update-motd b/update-motd index 7a4219b..5e73a65 100755 --- a/update-motd +++ b/update-motd @@ -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 diff --git a/update-motd.1 b/update-motd.1 index 55ec0c3..ddd70c7 100644 --- a/update-motd.1 +++ b/update-motd.1 @@ -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"