1#!/bin/bash 2# 3# 4# 5# IMPORTANT NOTE: THIS SCRIPT IS TO BE REPLACED BY THE MORE PORTABLE 6# check_system_crontabs.sh. 7# It is only kept here until we are confident the non-bash 8# version is stable. 9# 10# 11# 12# check_system_crontabs.bash 13# 14# Script to check and see if any system (f)crontabs have changed, and if so 15# build a fcrontab file from /etc/crontab, /etc/fcrontab and files from 16# /etc/cron.d/ and notify fcron about the change. 17# 18# WARNING : - if you run this script, your system fcrontab will be overridden 19# by the content of /etc/crontab, /etc/fcrontab, /etc/cron.d : 20# save the content of your system fcrontab first if necessary. 21# 22# - you should not have the same lines in /etc/crontab 23# and /etc/fcrontab, in which case the jobs would get run twice. 24# (/etc/crontab may for example be used for Vixie-cron compatible 25# lines, and /etc/fcrontab for the other ones) 26# 27# - you must understand that the contents of all the mentionned 28# files will go to a single file : the system fcrontab. 29# This means that you should pay attention to the global option 30# settings and environment variable assignments, which may 31# affect the other files too while you thought it wouldn't. 32# 33# This script was originally created for a Debian server. A number of 34# Debian packages like to drop files in /etc/cron.d/ and it would be nice 35# to have something automatically create a system fcrontab file and notify 36# fcron when those files change, so the system administrator doesn't have 37# to try and keep up with it all manually. 38# 39# It is planned that such feature is integreated directly in fcron 40# in the future (in a cleaner and more efficient way). Until then, 41# this script should be useful. 42# 43# I recommend running this script using dnotify or a similar program 44# (dnotify wait for a change in a file or a directory, and run a command 45# when it happens), with a something like that: 46# dnotify -b -p 1 -q 0 -MCDR /etc /etc/cron.d -e /usr/local/sbin/check_system_crontabs 47# in your boot scripts. 48# 49# Because we don't want the system fcrontab to be generated every few seconds 50# if the sys admin is working in /etc/ (the script has probably been called 51# by dnotify because of a change in /etc, but it may be a file not related 52# to fcron), the script will by default sleep so as to avoid being run too 53# often. The default sleep time is 30 seconds, and can be adjusted by changing 54# DEFAULT_SLEEP_TIME_BEFORE_REBUILD below, or by passing -s X, where X is 55# the number of seconds to sleep. X can be 0. 56# 57# If you can't use dnotify, you should run this script from the system fcrontab 58# with a line like this: 59# 60# @ 1 /usr/local/sbin/check_system_crontabs -s 0 61# 62# To force an immediate rebuild at the commandline try: 63# check_system_crontabs -f -i 64# 65# For more help on command-line options: 66# check_system_crontabs -h 67# 68# Changelog 69# ========= 70# Date Author Description 71# ---- ------ ----------- 72# 2004/11/12 maasj@dm.org Original version 73# 2005/02/24 Thibault Godouet Modified to be used with dnotify 74# + bug fixes and enhancement. 75# 2005/04/27 Daniel Himler Security enhancements and cleanups. 76# 2005/09/14 Damon Harper Command lines options, cleanups. 77# 78 79############################## 80# DEFAULT CONFIGURATION 81 82DEFAULT_SLEEP_TIME_BEFORE_REBUILD=30 83DEFAULT_CROND_DIR=/etc/cron.d 84DEFAULT_CRONTAB_FILE=/etc/crontab 85DEFAULT_FCRONTAB_FILE=/etc/fcrontab 86 87FCRONTAB_PROG=/usr/bin/fcrontab 88FCRONTABS_DIR=/var/spool/fcron 89 90# END OF DEFAULT CONFIGURATION 91############################## 92 93FCRONTAB_FILE_TMP= 94 95cleanup() { 96 # remove temporary file (if any) 97 [ -e "$FCRONTAB_FILE_TMP" ] && rm -f $FCRONTAB_FILE_TMP 98} 99trap "eval cleanup" INT TERM HUP 100 101if [ -x "`type -p mktemp`" ]; then 102 FCRONTAB_FILE_TMP=`mktemp /tmp/fcrontab.XXXXXX` 103else 104 FCRONTAB_FILE_TMP=/tmp/fcrontab.$$ 105fi 106 107info() { 108 [ -n "$VERBOSE" ] && echo "$@" >&2 109} 110 111die() { 112 echo check_system_crontabs: "$@" >&2 113 echo Try check_system_crontabs -h for help. >&2 114 exit 1 115} 116 117usage() { 118 cat <<_EOF_ >&2 119Description: Rebuild the systab file from various system crontabs. 120Usage: check_system_crontabs [options] 121 OPTIONS: 122 -v Verbose; tell what is happening. 123 -f Force rebuild, even if no changes are found. 124 -s SECONDS Sleep for SECONDS before rebuilding. 125 Default: $DEFAULT_SLEEP_TIME_BEFORE_REBUILD seconds. 126 -i Interactive use with no delay; same as -s 0. 127 -p PATHNAME Full path to or filename of the fcrontab binary; use this 128 only if it cannot be found automatically. 129 -F FILE System fcrontab file (default $DEFAULT_FCRONTAB_FILE). 130 -C FILE System crontab file (default $DEFAULT_CRONTAB_FILE). 131 -D DIR System crontab directory (default $DEFAULT_CROND_DIR). 132 -h This help text. 133_EOF_ 134 exit 135} 136 137SLEEP_TIME_BEFORE_REBUILD="$DEFAULT_SLEEP_TIME_BEFORE_REBUILD" 138CROND_DIR="$DEFAULT_CROND_DIR" 139CRONTAB_FILE="$DEFAULT_CRONTAB_FILE" 140FCRONTAB_FILE="$DEFAULT_FCRONTAB_FILE" 141FCRONTAB_PROG= 142VERBOSE= 143FORCE= 144 145# read command line arguments 146while [ "$#" -gt 0 ]; do 147 case "$1" in 148 -v) 149 VERBOSE=true 150 ;; 151 -f) 152 FORCE=true 153 ;; 154 -s) 155 SLEEP_TIME_BEFORE_REBUILD="$2" 156 shift 157 ;; 158 -i) 159 SLEEP_TIME_BEFORE_REBUILD=0 160 ;; 161 -p) 162 FCRONTAB_PROG="$2" 163 shift 164 ;; 165 -F) 166 FCRONTAB_FILE="$2" 167 shift 168 ;; 169 -C) 170 CRONTAB_FILE="$2" 171 shift 172 ;; 173 -D) 174 CROND_DIR="$2" 175 shift 176 ;; 177 -h) 178 usage 179 ;; 180 *) 181 die "Invalid option: $1!" 182 ;; 183 esac 184 shift 185done 186 187# find fcrontab executable path 188if [ -n "$FCRONTAB_PROG" ]; then 189 [ -d "$FCRONTAB_PROG" ] && FCRONTAB_PROG="$FCRONTAB_PROG/fcrontab" 190 [ ! -x "$FCRONTAB_PROG" ] && die "Invalid fcrontab executable or path specified with -p!" 191else 192 if [ -x "`type -p fcrontab`" ]; then 193 FCRONTAB_PROG="`type -p fcrontab`" 194 elif [ -x /usr/bin/fcrontab ]; then 195 FCRONTAB_PROG=/usr/bin/fcrontab 196 elif [ -x /usr/local/bin/fcrontab ]; then 197 FCRONTAB_PROG=/usr/local/bin/fcrontab 198 else 199 die "Unable to locate fcrontab binary! Specify with -p." 200 fi 201fi 202 203# sanity check 204if [ -z "$CROND_DIR" -o -z "$CRONTAB_FILE" -o -z "$FCRONTAB_FILE" ]; then 205 die "Must specify all system crontab files." 206fi 207 208# Function to scan for valid files in $CROND_DIR 209crond_files() 210{ 211 [ ! -d $CROND_DIR ] && return 212 local FILES=`echo $CROND_DIR/*` 213 local FILE 214 [ "$FILES" = "$CROND_DIR/*" ] && return 215 for FILE in $FILES; do 216 if [ ! -d $FILE -a $FILE = "${FILE%\~}" ]; then 217 echo $FILE 218 fi 219 done 220} 221 222 223# Function to build up a system crontab and tell fcron it's changed 224rebuild_and_notify() 225{ 226 logger -i -p cron.notice -t "check_system_crontabs" "Rebuilding the system fcrontab..." 227 228 # put a warning message at the top of the file 229 echo -e "########################################" > $FCRONTAB_FILE_TMP 230 echo -e "# WARNING!!! DO NOT EDIT THIS FILE!!! #" >> $FCRONTAB_FILE_TMP 231 echo -e "########################################" >> $FCRONTAB_FILE_TMP 232 echo -e "# Do not edit this file! It is automatically generated from" >> $FCRONTAB_FILE_TMP 233 echo -e "# the $CRONTAB_FILE, the $FCRONTAB_FILE and $CROND_DIR/* files whenever one of" >> $FCRONTAB_FILE_TMP 234 echo -e "# those files is changed.\n#\n\n" >> $FCRONTAB_FILE_TMP 235 236 # include the standard system crontab file if it exists and is not a symbolic link 237 if [ -f $CRONTAB_FILE -a ! -L $CRONTAB_FILE ]; then 238 echo -e "\n\n########################################\n# $CRONTAB_FILE\n########################################\n" >> $FCRONTAB_FILE_TMP 239 cat $CRONTAB_FILE >> $FCRONTAB_FILE_TMP 240 fi 241 242 # print a nice filename header for each file in /etc/cron.d/ 243 # and include its contents into the new fcron system crontab 244 for i in `crond_files` ; do 245 echo -e "\n\n########################################\n# $i\n########################################\n" >> $FCRONTAB_FILE_TMP 246 cat $i >> $FCRONTAB_FILE_TMP 247 done 248 249 # include the system fcrontab file if it exists and is not a symbolic link 250 if [ -f $FCRONTAB_FILE -a ! -L $FCRONTAB_FILE ]; then 251 echo -e "\n\n########################################\n# $FCRONTAB_FILE\n########################################\n" >> $FCRONTAB_FILE_TMP 252 cat $FCRONTAB_FILE >> $FCRONTAB_FILE_TMP 253 fi 254 255 # Replace "@hourly" style Vixie cron extensions which fcron doesn't parse 256 sed -i -e "s/@yearly/0 0 1 1 */g" -e "s/@annually/0 0 1 1 */g" -e "s/@monthly/0 0 1 * */g" -e "s/@weekly/0 0 * * 0/g" -e "s/@daily/0 0 * * */g" -e "s/@midnight/0 0 * * */g" -e "s/@hourly/0 * * * */g" $FCRONTAB_FILE_TMP 257 258 # notify fcron about the updated file 259 $FCRONTAB_PROG $FCRONTAB_FILE_TMP -u systab 260} 261 262NEED_REBUILD=0 263 264# by default, sleep to avoid too numerous executions of this script by dnotify. 265if [ -n "$SLEEP_TIME_BEFORE_REBUILD" -a "$SLEEP_TIME_BEFORE_REBUILD" != 0 ]; then 266 if ! sleep $SLEEP_TIME_BEFORE_REBUILD; then 267 # sleep time was invalid or sleep interrupted by signal! 268 cleanup 269 exit 1 270 fi 271fi 272 273# First check if we're forcing a rebuild: 274if [ -n "$FORCE" ]; then 275 276 NEED_REBUILD=1 277 278else 279 280 if [ -d $CROND_DIR ]; then 281 282 # This test works for file creation/deletion (deletion is not detected 283 # by the next test) 284 if [ $CROND_DIR -nt $FCRONTABS_DIR/systab.orig ]; then 285 286 info "Changes detected in $CROND_DIR" 287 NEED_REBUILD=1 288 289 else 290 291 # Test each one and see if it's newer than our timestamp file 292 for i in `crond_files` ; do 293 if [ $i -nt $FCRONTABS_DIR/systab.orig ]; then 294 295 info "Changes detected in $CROND_DIR" 296 NEED_REBUILD=1 297 298 fi 299 done 300 301 fi 302 303 fi 304 305 # Test the standard /etc/crontab file and see if it has changed 306 if [ -f $CRONTAB_FILE -a $CRONTAB_FILE -nt $FCRONTABS_DIR/systab.orig ]; then 307 308 info "Changes detected in $CRONTAB_FILE" 309 NEED_REBUILD=1 310 311 fi 312 313 # Test the standard /etc/fcrontab file and see if it has changed 314 if [ -f $FCRONTAB_FILE -a $FCRONTAB_FILE -nt $FCRONTABS_DIR/systab.orig ]; then 315 316 info "Changes detected in $FCRONTAB_FILE" 317 NEED_REBUILD=1 318 319 fi 320 321fi 322 323if [ $NEED_REBUILD -eq 1 ]; then 324 325 info "Rebuilding fcron systab." 326 rebuild_and_notify 327 328elif [ -n "$VERBOSE" ]; then 329 330 info "Not rebuilding fcron systab; no changes found." 331 332fi 333 334cleanup 335