Backup-Jobs: anacron vs. cron

cron

cron schedules execution of commands for certain times as given in crontab. But: If your DNS 323 has been switched off, execution is simply missed.

anacron

anacron makes sure that commands as given in /etc/cron.{hourly,daily,weekly,monthly}/ are executed exactly once in the apropriate period of time if system-uptime allows. As long as your NAS does not run 24h/day, anacron this is what you need to trigger f.e. daily/weekly/monthly rotating rsnapshot-backups of a local NAS-Path or a remote resource like your Notebook using a rsync-daemon installed there or a ssh-connection!

anacronism : alternative to anacron

Unfortunately there does not seem to be a suitable anacron-package (please correct me if this is not true). As a workaround you might use the shellscript anacronism which comes from the mythtv-community.(Thanks Marc !) .

#!/ffp/bin/sh
# set PATH to be run by crontab
PATH=/ffp/sbin:/usr/sbin:/sbin:/ffp/bin:/usr/bin:/bin ; export PATH

# nix /bin/bash
#
# $1: Path to cron directories. Default is "/etc/cron", which results in
#     processing all files in /etc/cron.daily, /etc/cron.weekly and
#     /etc/cron.monthly.
#
# $2: If the keyword is "reset", then all memory of when the last job
#     was run is erased and no other action is taken.
#
#       http://mythtv.mlaronson.com/home/anacron
#
# anacron-ersatz: sorgt dafür, dass die scripts in cron.{daily/weekly/monthly}
# nicht mehr als einmal in der jeweiligen periode ausgeführt werden
#
myname=$(basename $0)
logdir=/ffp/var/log
cache_dir=/ffp/var/cache/$myname
#
if [ "$1" == "" ]; then
  indir=/ffp/etc/cron
else
  indir="$1"
fi
log=$logdir/$myname.log
lastrun_filebase=$cache_dir/lastrun_$(echo "$indir" | sed -e "s@/@_@g")
days_since_epoch () {
  expr `date +"%s"` / 3600 / 24
  return 0
}

# Initialize
#
if [ "$USER" != "root" ]; then
  echo "$myname must be run as root"
  exit 1
fi
if [ ! -d "$logdir" ]; then mkdir -p "$logdir"; fi
if [ ! -d "$cache_dir" ]; then mkdir -p "$cache_dir"; fi
if [ ! -d $logdir ] || [ ! -w $logdir ]; then
  echo $0: Error, unable to create writing log directory named $logdir
  exit 1
fi
if [ ! -d $cache_dir ] || [ ! -w $cache_dir ]; then
  echo $0: Error, unable to create writing log directory named $cache_dir
  exit 1
fi
#
# Keep log sizes down
#
if [ -e $log ]; then
##  fsize=$( du --apparent-size -s "$log" | awk '{ print $1 }' )
  fsize=$( du -s "$log" | awk '{ print $1 }' )
  if [ $fsize -gt 50 ]; then
    echo "$myname: Log file size of $fsize KB cycled `date`." >> $log
    mv -f $log $log.-1
  fi
fi

#
# Main
#
if [ "$2" == "reset" ]; then
  echo "Resetting memory of when last run was made for $indir"
  rm -f $lastrun_filebase.daily $lastrun_filebase.weekly \
    $lastrun_filebase.monthly
  exit 0
fi
current_day=$( days_since_epoch )
echo "$myname: $indir on `date`, day number $current_day." >> $log
for line in "daily 1" "weekly 7" "monthly 30"; do
  unit_name=$(echo "$line" | cut -d" " -f1)
  unit_duration=$(echo "$line" | cut -d" " -f2)
  lastrun_file="$lastrun_filebase.$unit_name"
  if [ ! -d "$indir.$unit_name" ]; then
    echo "  Skipping $unit_name for $indir; $indir.$unit_name does not exist."
    continue
  fi
  if [ ! -e $lastrun_file ]; then
    lastrun_day=0
  else
    lastrun_day=$(cat $lastrun_file)
  fi
  nextrun_day=$( expr $lastrun_day + $unit_duration )
  echo "  Last $unit_name run was on" \
       "day $lastrun_day; next is on day $nextrun_day" >> $log
  if [ $nextrun_day -le $current_day ] && [ -d "$indir.$unit_name" ]; then
    #
    # Run the jobs
    #
    echo "    Running $unit_name jobs on day $current_day." >> $log
    #/usr/sbin/run-cron $indir.$unit_name 2>&1 \
    /ffp/bin/run-parts $indir.$unit_name 2>&1 \
     | sed -e "s/^/      /" >> $log
    echo $current_day > $lastrun_file
  fi
done
echo "" >> $log
echo "" >> $log
exit 0