4 REMOTE_DIR=/tmp/backmeupscotty/test
 
   5 ARCHIVE_KEEPNBACKUPS=30
 
   7 BACKUP_RUNEVERYNTHDAY=1
 
  14     date +'[%y-%m-%d|%H:%M:%S]'
 
  22     if [ $_ERROR_ENCOUNTERED -eq 0 ]; then
 
  29 function scottyerror {
 
  31     if [ $_ERROR_ENCOUNTERED -eq 0 ]; then
 
  33         scottyline "Going into verbose mode after error encounter." >&2
 
  41     if [ $sshret -eq 255 ]; then
 
  42         scottyerror "SSH connection failed!"
 
  49 function grepbackups {
 
  50     ssh255 $REMOTE_HOST "ls $REMOTE_DIR" | grep -E '[0-9]+-[0-9]+'
 
  53 function isIncomplete {
 
  54     if ( ssh255 $REMOTE_HOST '[ -d '$REMOTE_DIR/incomplete' ]' ); then
 
  62     if [ $(( ( $(date +%s) / (60*60*24) ) % $BACKUP_RUNEVERYNTHDAY )) -eq 0 ];
 
  70 function latestTooOld {
 
  71     for oldbackup in $(grepbackups); do
 
  72         tstamp=$(echo $oldbackup | cut -d'-' -f1)
 
  74         if [ $(( $(date +%s) - $tstamp )) -lt $(( ($BACKUP_RUNEVERYNTHDAY*24+12)*60*60 )) ]
 
  86     scottyinfo "Syncing $SYNC_SRC to $REMOTE_HOST:$REMOTE_DIR @$timestamp."
 
  88     if [ ! -d "$SYNC_SRC" ]; then
 
  89         scottyerror "Source dir $SYNC_SRC does not exist. Not syncing!"
 
  93     if [ $(ls -A "$SYNC_SRC" | wc -l) -eq 0 ]; then
 
  94         scottyerror "Source dir $SYNC_SRC is empty. Not syncing!"
 
  98     dir_current=$REMOTE_DIR/current
 
  99     dir_incomplete=$REMOTE_DIR/incomplete
 
 100     dir_timestamped=$REMOTE_DIR/$timestamp-$(date -d @$timestamp +%Y%m%d%H%M%S)
 
 102     if [ -z $SYNC_EXC ]; then
 
 105         rsync_exclude=$(eval echo --exclude={$SYNC_EXC} | tr -d {})
 
 108     if (ssh255 $REMOTE_HOST '[ ! -d '$REMOTE_DIR' ]'); then
 
 109         scottyinfo "Creating destination directory $REMOTE_HOST:$REMOTE_DIR."
 
 110         ssh255 $REMOTE_HOST "mkdir $REMOTE_DIR"
 
 113     if isIncomplete; then
 
 114         scottyerror "Continuing old incomplete backup."
 
 117     scottyinfo "Starting rsync."
 
 118     rsync -e ssh --bwlimit=$BWLIMIT \
 
 119           -v -aHAX --numeric-ids --delete --delete-excluded \
 
 120           --link-dest=$dir_current \
 
 122           $SYNC_SRC/ $REMOTE_HOST:$dir_incomplete/
 
 124     if [ $? -eq 0 ]; then
 
 125         scottyinfo "Timestamping completed backup and linking to current backup."
 
 126         ssh255 $REMOTE_HOST \
 
 127                "mv $dir_incomplete $dir_timestamped && rm -f $dir_current && \
 
 128                ln -s $(basename $dir_timestamped) $dir_current"
 
 130         scottyerror "Rsync failed."
 
 133     while [ $(grepbackups | wc -l) -gt $ARCHIVE_KEEPNBACKUPS ]; do
 
 134         oldestbackup=$(grepbackups | head -1)
 
 135         oldestbackuptstamp=$(echo $oldestbackup | cut -d'-' -f1)
 
 137         if [ $oldestbackuptstamp -lt $(( $(date +%s) - $ARCHIVE_KEEPNDAYS*60*60*24 )) ]; then
 
 138             scottyinfo "Removing old backup $oldestbackup."
 
 139             ssh255 $REMOTE_HOST rm -r "$REMOTE_DIR/$oldestbackup"
 
 146 function deleteLock {
 
 147     if ! rmdir /var/lock/$(basename $0); then
 
 148         scottyerror "Could not delete lockfile /tmp/$(basename $0).lock!"
 
 152 function cleanup_abort {
 
 153     scottyerror "Caught exit signal! Cleaning up."
 
 157     if [ $(jobs -p) ]; then
 
 158         scottyerror "TERMinating remaining child processes."
 
 168     scottyinfo "No cleanup function was defined."
 
 172     scottyinfo "No prepare function was defined."
 
 175 function cleanup_normal {
 
 182 Usage: $(basename $0) [OPTION]...
 
 185   -q   Only output errors
 
 186   -n   Run only on nth day
 
 188   -l   List existing backups
 
 189   -h   Print out this help
 
 193 function exclusiveLock {
 
 194     if ! mkdir /var/lock/$(basename $0); then
 
 195         scottyerror "Another instance of $(basename $0) is still running!"
 
 202 function backmeupscotty {
 
 203     while getopts "qn:flh" opt; do
 
 209                 BACKUP_RUNEVERYNTHDAY=$OPTARG
 
 224     ssh255 $REMOTE_HOST exit
 
 226     if [ $LIST_BACKUPS ]; then
 
 227         for backup in $(grepbackups); do
 
 235     if [ $BACKUP_FORCE -eq 1 ]; then
 
 236         scottyinfo "Backup was enforced."
 
 237     elif latestTooOld; then
 
 238         scottyerror "The latest backup is too old."
 
 240         scottyinfo "This is the nth day."
 
 242         scottyinfo "No backup has to be done. Exiting."
 
 246     scottyinfo "Performing backup."
 
 248     trap cleanup_abort EXIT
 
 253     trap cleanup_normal EXIT