#!/bin/sh

# Karsten Kruse - www.tecneeq.de
#
# tecback - make daily, unattended backups
#
#  Install:
#   1) Put the script into a directory with a lot space and make it
#      executeable: chmod 700 tecback
#   2) Adjust the settings (see below):
#        * holdbackup  - delete backups that are older than $holdbackup
#                        days
#        * zip         - full path to your zip binary (required is
#                        info-zip 2.3 or newer, check www.info-zip.org)
#        * basedir     - full path to tecback's directory
#        * include     - directorys to include in the backup
#        * exclude     - directorys to exclude from the backup
#        * verbose     - be verbose or not
#   3) Start tecback with the full path to check that everything is ok
#   4) Add a job to your crontab:
#         * start the crontab-editor as root:
#           crontab -e
#         * to run tecback every day at 02:10 insert this:
#           10 2 * * * nice /pfad/tecback

holdbackup=120
zip=/usr/pkg/bin/zip
basedir=/mnt/data2/_backup
verbose=no

include="
/etc
/home
/root
/usr/X11R6/lib/X11/xdm
/usr/local/updee
/usr/pkg/etc
/usr/share/sendmail/m4
/var/backups/work
/var/cron/tabs
/var/games
/var/mysql
/var/named
/var/spool/mqueue
/var/spool/squirrelmail
/var/mail
"

exclude="
/home/pusty
/home/tarra
"

#  Copyright (c) 2003-04, Karsten Kruse tecneeq(at)tecneeq(dot)de
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following  disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in
#     the documentation and/or other materials provided with the
#     distribution.
#  3. Neither the name of the author nor the names of its contributors
#     may be used to endorse or promote products derived from this
#     software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

###### DO NOT EDIT BELOW ####################################################

bomb() {
  echo ERROR: $1
  exit 1
}

workdir=${basedir}/archive
stampfile=${workdir}/.stampfile
stampfilerun=${workdir}/.stampfile_run
hostname=`hostname -s`
monthday=`date +%d`
epoch=`date +%d.%m.%y_%H:%M:%S`
no_compress="-n .Z:.gz:.bz2:.tar.gz:.tgz:.tar.bz2:.tbz:.mp3:.avi:.mpg:.mpeg:.zip:.rar:.ace"

# do some tests
if [ ! -x $zip ] ; then
  bomb "$zip not found, wrong path?"
fi
if [ `$zip -h | grep '^Zip ' | awk '{print $2}' | sed 's/\.//'` -lt 23 ] ; then
  bomb "Your $zip is too old. We need info-zip 2.3 or newer."
fi
if [ ! -d $workdir ] ; then
  mkdir -p $workdir || bomb "could not create $workdir, not enough rights?"
fi

# verbose or not?
if [ ! $verbose = yes ] ; then
  quiet="-q"
else
  quiet=""
fi

# setup include and exclude-lines
for i in $include ; do
  if [ -d $i ] ; then
    includeline="$i $includeline"
  else
    echo "$i in \$include does not exist and is ignored, check that"
  fi
done
for i in $exclude $workdir ; do
  if [ -d $i ] ; then
    ignoreline="-e $i $ignoreline"
  else
    echo "$i in \$exclude does not exist and is ignored"
  fi
done

# needed since find, even if it has not found a file, exits with 0
fullbackups=0
for i in `find $workdir -type f -name "${hostname}_full*" -print` ; do
  fullbackups=1
done

# full or incremental backup?
if [ `date +%d` = 01 -o ! -f $stampfile -o $fullbackups = 0 ] ; then
  kind=full
else
  kind=increment
fi

# set title of backup
title=${workdir}/${hostname}_${kind}_${epoch}.zip

# here we do some work
if [ $kind = increment ] ; then
  last_backup=`ls -l $stampfile | awk '{print $7"."$6".",$8}'`
  echo "==> performing incremental backup (new files since $last_backup)"
  touch $stampfilerun
  find $includeline -type f -newer $stampfile -print \
    | grep -v ${ignoreline} | $zip $quiet -y $no_compress -@ $title
  mv $stampfilerun $stampfile
elif [ $kind = full ] ; then
  echo "==> performing full backup ..."
  touch $stampfilerun
  find $includeline -print \
    | grep -v ${ignoreline} | $zip $quiet -y $no_compress -@ $title
  mv $stampfilerun $stampfile
fi

# delete old backups
find $workdir -type f -name "${hostname}_*.zip" -ctime +$holdbackup -exec rm {} \;
echo "==> ... done"

# eof
