4 REMOTE_DIR=/tmp/backmeupscotty/test
 
   5 ARCHIVE_KEEPNBACKUPS=30
 
   7 BACKUP_RUNEVERYNTHDAY=1
 
  10     echo $(basename $0) | tr '[:lower:]' '[:upper:]'
 
  17 function scottyerror {
 
  18     echo $(upperme): $@ >&2 
 
  21 function grepbackups {
 
  22     ssh $REMOTE_HOST "ls $REMOTE_DIR" | grep -E '[0-9]+-[0-9]+'
 
  25 function isIncomplete {
 
  26     if ( ssh $REMOTE_HOST '[ -d '$REMOTE_DIR/incomplete' ]' ); then
 
  34     if [ $(( ( $(date +%s) / (60*60*24) ) % $BACKUP_RUNEVERYNTHDAY )) -eq 0 ]; 
 
  42 function latestTooOld {
 
  43     for oldbackup in $(grepbackups); do
 
  44         tstamp=$(echo $oldbackup | cut -d'-' -f1)
 
  46         if [ $(( $(date +%s) - $tstamp )) -lt \
 
  47             $(( $BACKUP_RUNEVERYNTHDAY*24*60*60 )) ]
 
  59     scottyinfo Syncing $SYNC_SRC to $REMOTE_HOST:$REMOTE_DIR @$timestamp
 
  61     if [ ! -d "$SYNC_SRC" ]; then
 
  62         scottyerror Source dir $SYNC_SRC does not exist. Not syncing!
 
  66     if [ $(ls -A "$SYNC_SRC" | wc -l) -eq 0 ]; then
 
  67         scottyerror Source dir $SYNC_SRC is empty. Not syncing!
 
  71     dir_current=$REMOTE_DIR/current
 
  72     dir_incomplete=$REMOTE_DIR/incomplete
 
  73     dir_timestamped=$REMOTE_DIR/$timestamp-$(date -d @$timestamp +%Y%m%d%H%M%S)
 
  75     if [ -z $SYNC_EXC ]; then
 
  78         rsync_exclude=$(eval echo --exclude={$SYNC_EXC} | tr -d {})
 
  81     if (ssh $REMOTE_HOST '[ ! -d '$REMOTE_DIR' ]'); then
 
  82         scottyinfo Creating destination directory $REMOTE_HOST:$REMOTE_DIR
 
  83         ssh $REMOTE_HOST "mkdir $REMOTE_DIR"
 
  87         scottyerror Continuing old incomplete backup
 
  90     scottyinfo Starting rsync
 
  92         -v -aHAX --numeric-ids --delete --delete-excluded \
 
  93         --link-dest=$dir_current \
 
  95         $SYNC_SRC/ $REMOTE_HOST:$dir_incomplete/
 
  98         scottyinfo Timestamping completed backup and linking to current backup
 
 100             "mv $dir_incomplete $dir_timestamped && rm -f $dir_current && ln -s $(basename $dir_timestamped) $dir_current"
 
 103     while [ $(grepbackups | wc -l) -gt $ARCHIVE_KEEPNBACKUPS ]; do
 
 104         oldestbackup=$(grepbackups | head -1)
 
 105         oldestbackuptstamp=$(echo $oldestbackup | cut -d'-' -f1)
 
 107         if [ $oldestbackuptstamp -lt $(( $(date +%s) - $ARCHIVE_KEEPNDAYS*60*60*24 )) ]; then
 
 108             scottyinfo Removing old backup $oldestbackup
 
 109             ssh $REMOTE_HOST rm -r "$REMOTE_DIR/$oldestbackup"
 
 116 function deleteLock {
 
 117     if ! rmdir /tmp/$(basename $0).lock; then
 
 118         scottyerror "Could not delete lockfile /tmp/$(basename $0).lock!"
 
 123     scottyinfo "Preparing for sync"
 
 126 function cleanup_abort {
 
 127     scottyerror "Caught exit signal! Cleaning up..."
 
 131     if [ $(jobs -p) ]; then
 
 132         scottyerror TERMinating remaining child processes...
 
 142     scottyinfo "No cleanup function was defined."
 
 146     scottyinfo "No prepare function was defined."
 
 149 function cleanup_normal {
 
 156 Usage: $(basename $0) [OPTION]...
 
 159   -q   Only output errors
 
 160   -n   Run only on nth day
 
 161   -h   Print out this help
 
 165 function backmeupscotty {
 
 166     while getopts "qn:h" opt; do
 
 172                 BACKUP_RUNEVERYNTHDAY=$OPTARG
 
 182         scottyinfo "This is the nth day."
 
 183     elif latestTooOld; then
 
 184         scottyinfo "The latest backup is too old."
 
 186         scottyinfo "No backup has to be done. Exiting."
 
 190     scottyinfo "Performing backup."
 
 192     trap cleanup_abort EXIT
 
 197     trap cleanup_normal EXIT
 
 202 if ! mkdir /tmp/$(basename $0).lock; then
 
 203     scottyerror "Another instance of $(basename $0) is still running!"