[OpenBSDsupport]

Backup script example for user that don't have tape recorders.

#!/bin/sh
# Originally by Nicholas Marriott

#   NOTE!
#1. You can ignore parts of dirs by putting relative paths to
#   SOURCES entry in, eg $ROOT/home.ignore -- be aware script will 
#   chflags them nodump
#2. Unless your SOURCES are a mount point dump will always do a level 0 backup
#3. rename the script to daily.local and place it in /etc
#4. Edit /etc/daily and add:
#   if [ -f /etc/daily.local ];then
#   echo "Running daily.local"
#   . /etc/daily.local
#   echo ""
#   fi

#path to backup destination
ROOT=/backup

#directories and mountpoints that you want to dump
SOURCES="/home /etc /var"

#cat for no compression or gzip if you wish compression
COMPRESS=cat

#file extension
EXT=

# check free space
USED=`df $ROOT|awk '/^\// { print substr($5, 0, length($5) - 1) }'`
if [ $USED -gt 75 ]; then
    echo "-------------------------------------------------------------------"
    echo "INSUFFICIENT DISK SPACE"
    echo "-------------------------------------------------------------------"
    df -h $ROOT
    exit
fi

# dump sequence. FULL is 0, RESET is 1, and PATTERN is followed between RESETs
FULL=20
RESET=10
#modified Tower of Hanoi algorithm, with
#this sequence of dump levels
set -A PATTERN 3 2 5 4 7 6 9 8 9 9

# get the last day
if [ -f $ROOT/day ]; then
    DAY=$(< $ROOT/day)
else
    DAY=0
fi

if [ $(($DAY % $FULL)) -eq 0 ]; then
    LEVEL=0
    DAY=0
elif [ $(($DAY % $RESET)) -eq 0 ]; then
    LEVEL=1
else
    LEVEL=${PATTERN[$(((DAY % $RESET) - 1))]}
fi

DATE="`date +%Y%m%d`"
for i in $SOURCES; do
    NAME="`echo $i|sed 's/^\///; s/\/$//; s/\//_/'`"
    TARGET="$ROOT/$NAME"
    mkdir -p "$TARGET"

    FILE="$TARGET/$NAME-`printf '%0.2d' $DAY`-$DATE.$LEVEL"
    echo "-------------------------------------------------------------------"
    echo "$i $LEVEL $DATE $FILE"

    if [ -f "$TARGET.ignore" ]; then
	while read j; do
	    (echo $j|grep '\.\.' >/dev/null) && echo illegal $i/$j && continue
	    (echo $j|grep '^/'   >/dev/null) && echo illegal $i/$j && continue
	    echo ignore $i/$j
	    chflags -R nodump "$i/$j" || exit
	done < "$TARGET.ignore"
    fi

    if [ $LEVEL -eq 0 ]; then
	# save list of files for removal
	ls -d "$TARGET"/* 2>/dev/null >"$TARGET/list"
	[ ! -s "$TARGET/list" ] && rm -f "$TARGET/list"
    fi

    time (dump -h0 -u$LEVEL -f - $i|$COMPRESS >"$FILE$EXT") 2>&1| \
	tee "$FILE.log" || exit

    if [ $LEVEL -eq 0 -a -f "$TARGET/list" ]; then
	# clean up old files
	xargs rm -f -- <"$TARGET/list"
	rm -f "$TARGET/list"
    fi
    if [ $LEVEL -eq 1 ]; then
	# remove everything except level 0 and 1
	rm -f -- "$TARGET"/*.[2-9]*
    fi
done
echo "-------------------------------------------------------------------"
df -h $ROOT

# update day
DAY=$(($DAY + 1))
echo $DAY >$ROOT/day