kbackup
started life as many backup programs do; as a set of bash scripts. Bash scripts can be quick-and-easy
automation solutions but they have many issues assiocaited with them. The biggest of these is the text-based nature of
the environment.
The pragmatic programmer talks about prototypes. They cover the topic briefly here but I recommend reading the actual book .
Our bash script eventually ended up being the prototype and looked something like this:
#!/usr/bin/env bash
set -eo pipefail
[[ -z $1 ]] && echo "No sources provided" && exit 1
[[ -z $2 ]] && echo "No destination provided" && exit 1
SOURCES="${@:1:$#-1}"
DESTINATION="${@: -1}"
for SOURCE in $SOURCES
do
TARGET=`basename $SOURCE`
mkdir -pv $DESTINATION/$TARGET/.kbackup
CURRENT=`date -Is | head -c 19 | sed "s/:/-/g"`
if [[ -e $DESTINATION/$TARGET/.kbackup/last ]]
then
LAST=`cat $DESTINATION/$TARGET/.kbackup/last`
echo "> Rotating last backup: $DESTINATION/$TARGET/.kbackup/$LAST"
mkdir -pv $DESTINATION/$TARGET/.kbackup/$LAST
ls -A $DESTINATION/$TARGET | grep -v '.kbackup' | while read f; do echo "$DESTINATION/$TARGET/$f"; done \
| xargs -d '\n' cp -al -t $DESTINATION/$TARGET/.kbackup/$LAST
else
echo "> No existing backups"
fi
echo "> Backing up: $SOURCE -> $DESTINATION/$TARGET"
rsync -hav --delete --exclude .kbackup "$SOURCE/" "$DESTINATION/$TARGET" || (
[[ $LAST ]] &&
echo "> Cleaning up: $DESTINATION/$TARGET/.kbackup/$LAST" &&
rm -rf $DESTINATION/$TARGET/.kbackup/$LAST &&
exit 1
)
echo "$CURRENT" > $DESTINATION/$TARGET/.kbackup/last
done