CRON problem after Daylight time change

Jim Knutson knutson%sw.mcc.com at mcc.com
Fri Jun 28 06:22:00 AEST 1991


I posted this to sun-managers a while back.  It will restart cron appropriately
at each time change.


# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by knutson on Wed Jun 12 13:25:51 CDT 1991
# Contents:  dstcronfix

echo x - dstcronfix
sed 's/^@//' > "dstcronfix" <<'@//E*O*F dstcronfix//'
#!/bin/sh
# @(#)dstcronfix	1.3	4/15/91
#
# NAME
#	dstcronfix - restart cron when DST changes
#
# SYNOPSIS
#	dstcronfix
#
# DESCRIPTION
#	dstcronfix determines when the next DST change takes place and
#	then schedules an at job to restart cron after the change has
#	taken place.
#
#	The at job is scheduled to start just before the time change.
#	It then waits until the time change has occured before killing
#	and restarting cron.  It also reschedules itself for the next 
#	DST change.
#
#	The leadtime for scheduling is set in the script and should be
#	set to a value which will allow cron to run it before the DST
#	change occurs.  For SunOS 4.0 and greater, at/cron have a 1
#	minute granularity.  Other systems which execute atrun from
#	cron must set the lead time to account for the granularity in
#	running atrun.
#
# SEE ALSO
#	at(1), cron(8), zdump(8)
#
# AUTHOR
#	Jim Knutson <knutson at mcc.com>
#
# BUGS
#	Restarts cron twice in the fall.
#
TIMEZONE=US/Central
LEADTIME=1			# number of minutes of lead time
TMP=/tmp/.dst$$
PATH=/usr/bin:/usr/ucb:/usr/etc

# return month number for a given month name
monthnum() {
	case "$1" in
	Jan) echo 01;;
	Feb) echo 02;;
	Mar) echo 03;;
	Apr) echo 04;;
	May) echo 05;;
	Jun) echo 06;;
	Jul) echo 07;;
	Aug) echo 08;;
	Sep) echo 09;;
	Oct) echo 10;;
	Nov) echo 11;;
	Dec) echo 12;;
	esac
}

# compare two dates of the form "MMM YY HH:MM:SS YYYY" and
# return <0 if date1 < date2, 0 if date1 = date2, >0 if date1 > date2
datecmp() {
	eval `echo "$1" | sed 's/:/ /g' | awk '{printf "mon1=%s day1=%s hr1=%s min1=%s sec1=%s yr1=%s\n",$1,$2,$3,$4,$5,$6}'`
	eval `echo "$2" | sed 's/:/ /g' | awk '{printf "mon2=%s day2=%s hr2=%s min2=%s sec2=%s yr2=%s\n",$1,$2,$3,$4,$5,$6}'`
	diff=`expr $yr1 - $yr2`
	if [ $diff -ne 0 ]; then
		echo $diff
		return
	fi
	mm1=`monthnum $mon1`
	mm2=`monthnum $mon2`
	diff=`expr $mm1 - $mm2`
	if [ $diff -ne 0 ]; then
		echo $diff
		return
	fi
	diff=`expr $day1 - $day2`
	if [ $diff -ne 0 ]; then
		echo $diff
		return
	fi
	diff=`expr $hr1 - $hr2`
	if [ $diff -ne 0 ]; then
		echo $diff
		return
	fi
	diff=`expr $min1 - $min2`
	if [ $diff -ne 0 ]; then
		echo $diff
		return
	fi
	diff=`expr $sec1 - $sec2`
	echo $diff
	return
}

# translate a date of the form "MMM DD HH:MM:SS YYYY" into a
# form suitable for use with the at command.
atdate () {
	eval `echo $* | sed 's/:/ /g' | awk '{printf "mon=%s day=%s hr=%s min=%s sec=%s yr=%s\n",$1,$2,$3,$4,$5,$6}'`
	min=`expr $min - $LEADTIME`
	if [ $min -lt 0 ]; then
		echo "`basename $0`: too much lead time"
	fi
	echo "$hr:$min $mon $day"
}

# get seconds from a date of the form "MMM DD HH:MM:SS YYYY"
seconds() {
	expr "$*" : '.*:..:\(..\) .*'
}

# get DST change data
trap "rm -f $TMP; exit 1" 2 3
zdump -v $TIMEZONE >$TMP

# save the current date for comparison
set `head -1 $TMP`
NOW="$3 $4 $5 $6"
THISYEAR=$6

# look at the DST change data and find the next change
sed -e '1d' -e 's/isdst=//' -e 's/.*= ... //' $TMP | \
while read timeinfo; do
	set $timeinfo

	# speed things up by ignoring old years
	if [ $THISYEAR -gt $4 ]; then
		continue
	fi

	DATE="$1 $2 $3 $4"
	# if this DST change is in the future
	if [ `datecmp "$NOW" "$DATE"` -lt 0 ]; then
		# schedule at job to fix cron and start the cycle all over again
		at `atdate $DATE` <<!
			# sleep for the leadtime we specified to make sure
			# the DST change has occured.  Add seconds before change
			# and a fudge to make sure cron is through processing.
			sleep `expr $LEADTIME \* 60 + \`seconds $DATE\` + 10`
			echo Restarting cron due to DST change
			pid=\`ps ax | grep -w cron | grep -v grep | awk '{print \$1}'\`
			kill \$pid
			cron
			# Start the cycle over again
			echo Scheduling next cron restart
			$0
!
		break
	fi
done


# remove tmp file
rm -f $TMP
@//E*O*F dstcronfix//
chmod u=r,g=r,o=r dstcronfix

exit 0




More information about the Comp.sys.sun mailing list