4 REMOTE_DIR=/tmp/backmeupscotty/test
 
   5 ARCHIVE_KEEPNBACKUPS=30
 
   7 BACKUP_RUNEVERYNTHDAY=1
 
   9 _UPPERME=$(echo $(basename $0) | tr '[:lower:]' '[:upper:]')
 
  12     date +"[%y-%m-%d %H:%M:%S]"
 
  16     echo $(timestamp) $_UPPERME: $@ 
 
  19 function scottyerror {
 
  20     echo $(timestamp) $_UPPERME: $@ >&2 
 
  27     if [ $sshret -eq 255 ]; then
 
  28         scottyerror "SSH connection failed!"
 
  35 function grepbackups {
 
  36     ssh255 $REMOTE_HOST "ls $REMOTE_DIR" | grep -E '[0-9]+-[0-9]+'
 
  39 function isIncomplete {
 
  40     if ( ssh255 $REMOTE_HOST '[ -d '$REMOTE_DIR/incomplete' ]' ); then
 
  48     if [ $(( ( $(date +%s) / (60*60*24) ) % $BACKUP_RUNEVERYNTHDAY )) -eq 0 ]; 
 
  56 function latestTooOld {
 
  57     for oldbackup in $(grepbackups); do
 
  58         tstamp=$(echo $oldbackup | cut -d'-' -f1)
 
  60         if [ $(( $(date +%s) - $tstamp )) -lt \
 
  61             $(( ($BACKUP_RUNEVERYNTHDAY*24+12)*60*60 )) ]
 
  73     scottyinfo "Syncing $SYNC_SRC to $REMOTE_HOST:$REMOTE_DIR @$timestamp."
 
  75     if [ ! -d "$SYNC_SRC" ]; then
 
  76         scottyerror "Source dir $SYNC_SRC does not exist. Not syncing!"
 
  80     if [ $(ls -A "$SYNC_SRC" | wc -l) -eq 0 ]; then
 
  81         scottyerror "Source dir $SYNC_SRC is empty. Not syncing!"
 
  85     dir_current=$REMOTE_DIR/current
 
  86     dir_incomplete=$REMOTE_DIR/incomplete
 
  87     dir_timestamped=$REMOTE_DIR/$timestamp-$(date -d @$timestamp +%Y%m%d%H%M%S)
 
  89     if [ -z $SYNC_EXC ]; then
 
  92         rsync_exclude=$(eval echo --exclude={$SYNC_EXC} | tr -d {})
 
  95     if (ssh255 $REMOTE_HOST '[ ! -d '$REMOTE_DIR' ]'); then
 
  96         scottyinfo "Creating destination directory $REMOTE_HOST:$REMOTE_DIR."
 
  97         ssh255 $REMOTE_HOST "mkdir $REMOTE_DIR"
 
 100     if isIncomplete; then
 
 101         scottyerror "Continuing old incomplete backup."
 
 104     scottyinfo "Starting rsync."
 
 106         -v -aHAX --numeric-ids --delete --delete-excluded \
 
 107         --link-dest=$dir_current \
 
 109         $SYNC_SRC/ $REMOTE_HOST:$dir_incomplete/
 
 111     if [ $? -eq 0 ]; then
 
 112         scottyinfo "Timestamping completed backup and linking to current backup."
 
 113         ssh255 $REMOTE_HOST \
 
 114             "mv $dir_incomplete $dir_timestamped && rm -f $dir_current && ln -s $(basename $dir_timestamped) $dir_current"
 
 117     while [ $(grepbackups | wc -l) -gt $ARCHIVE_KEEPNBACKUPS ]; do
 
 118         oldestbackup=$(grepbackups | head -1)
 
 119         oldestbackuptstamp=$(echo $oldestbackup | cut -d'-' -f1)
 
 121         if [ $oldestbackuptstamp -lt $(( $(date +%s) - $ARCHIVE_KEEPNDAYS*60*60*24 )) ]; then
 
 122             scottyinfo "Removing old backup $oldestbackup."
 
 123             ssh255 $REMOTE_HOST rm -r "$REMOTE_DIR/$oldestbackup"
 
 130 function deleteLock {
 
 131     if ! rmdir /var/lock/$(basename $0); then
 
 132         scottyerror "Could not delete lockfile /tmp/$(basename $0).lock!"
 
 136 function cleanup_abort {
 
 137     scottyerror "Caught exit signal! Cleaning up."
 
 141     if [ $(jobs -p) ]; then
 
 142         scottyerror "TERMinating remaining child processes."
 
 152     scottyinfo "No cleanup function was defined."
 
 156     scottyinfo "No prepare function was defined."
 
 159 function cleanup_normal {
 
 166 Usage: $(basename $0) [OPTION]...
 
 169   -q   Only output errors
 
 170   -n   Run only on nth day
 
 171   -h   Print out this help
 
 175 function backmeupscotty {
 
 176     while getopts "qn:h" opt; do
 
 182                 BACKUP_RUNEVERYNTHDAY=$OPTARG
 
 191     ssh255 $REMOTE_HOST exit
 
 193     if latestTooOld; then
 
 194         scottyerror "The latest backup is too old."
 
 196         scottyinfo "This is the nth day."
 
 198         scottyinfo "No backup has to be done. Exiting."
 
 202     scottyinfo "Performing backup."
 
 204     trap cleanup_abort EXIT
 
 209     trap cleanup_normal EXIT
 
 214 if ! mkdir /var/lock/$(basename $0); then
 
 215     scottyerror "Another instance of $(basename $0) is still running!"