]> git.treefish.org Git - backmeupscotty.git/blob - backmeupscotty
07a20496a054dc83c54b6351109d837dd6ce4d9d
[backmeupscotty.git] / backmeupscotty
1 #!/bin/bash
2
3 REMOTE_HOST=localhost
4 REMOTE_DIR=/tmp/backmeupscotty/test
5 ARCHIVE_KEEPNBACKUPS=30
6 ARCHIVE_KEEPNDAYS=30
7 BACKUP_RUNEVERYNTHDAY=1
8
9 function upperme {
10     echo $(basename $0) | tr '[:lower:]' '[:upper:]'
11 }
12
13 function scottyinfo {
14     echo $(upperme): $@ 
15 }
16
17 function scottyerror {
18     echo $(upperme): $@ >&2 
19 }
20
21 function grepbackups {
22     ssh $REMOTE_HOST "ls $REMOTE_DIR" | grep -E '[0-9]+-[0-9]+'
23 }
24
25 function isIncomplete {
26     if ( ssh $REMOTE_HOST '[ -d '$REMOTE_DIR/incomplete' ]' ); then
27         return 0
28     else
29         return 1
30     fi
31 }
32
33 function isIncompleteOrNthDay {
34     if isIncomplete || \
35         [ $(( ( $(date +%s) / (60*60*24) ) % $BACKUP_RUNEVERYNTHDAY )) -eq 0 ]; 
36     then
37         return 0
38     else
39         return 1
40     fi  
41 }
42
43 function scottysync {
44     timestamp=$(date +%s)
45
46     scottyinfo Syncing $SYNC_SRC to $REMOTE_HOST:$REMOTE_DIR @$timestamp
47
48     if [ ! -d "$SYNC_SRC" ]; then
49         scottyerror Source dir $SYNC_SRC does not exist. Not syncing!
50         return 1
51     fi
52
53     if [ $(ls -A "$SYNC_SRC" | wc -l) -eq 0 ]; then
54         scottyerror Source dir $SYNC_SRC is empty. Not syncing!
55         return 1
56     fi
57
58     dir_current=$REMOTE_DIR/current
59     dir_incomplete=$REMOTE_DIR/incomplete
60     dir_timestamped=$REMOTE_DIR/$timestamp-$(date -d @$timestamp +%Y%m%d%H%M%S)
61
62     if [ -z $SYNC_EXC ]; then
63         rsync_exclude=""
64     else
65         rsync_exclude=$(eval echo --exclude={$SYNC_EXC} | tr -d {})
66     fi
67
68     if (ssh $REMOTE_HOST '[ ! -d '$REMOTE_DIR' ]'); then
69         scottyinfo Creating destination directory $REMOTE_HOST:$REMOTE_DIR
70         ssh $REMOTE_HOST "mkdir $REMOTE_DIR"
71     fi
72
73     if isIncomplete; then
74         scottyerror Continuing old incomplete backup
75     fi
76
77     scottyinfo Starting rsync
78     rsync -e ssh \
79         -v -aHAX --numeric-ids --delete --delete-excluded \
80         --link-dest=$dir_current \
81         $rsync_exclude \
82         $SYNC_SRC/ $REMOTE_HOST:$dir_incomplete/
83     
84     if [ $? -eq 0 ]; then
85         scottyinfo Timestamping completed backup and linking to current backup
86         ssh $REMOTE_HOST \
87             "mv $dir_incomplete $dir_timestamped && rm -f $dir_current && ln -s $(basename $dir_timestamped) $dir_current"
88     fi
89
90     while [ $(grepbackups | wc -l) -gt $ARCHIVE_KEEPNBACKUPS ]; do
91         oldestbackup=$(grepbackups | head -1)
92         oldestbackuptstamp=$(echo $oldestbackup | cut -d'-' -f1)
93
94         if [ $oldestbackuptstamp -lt $(( $(date +%s) - $ARCHIVE_KEEPNDAYS*60*60*24 )) ]; then
95             scottyinfo Removing old backup $oldestbackup
96             ssh $REMOTE_HOST rm -r "$REMOTE_DIR/$oldestbackup"
97         else
98             break
99         fi
100     done
101 }
102
103 function deleteLock {
104     if ! rmdir /tmp/$(basename $0).lock; then
105         scottyerror "Could not delete lockfile /tmp/$(basename $0).lock!"
106     fi
107 }
108
109 function prepare {
110     scottyinfo "Preparing for sync"
111 }
112
113 function cleanup_abort {
114     scottyinfo "No cleanup_abort function was defined."
115 }
116
117 function _cleanup_abort {
118     scottyerror "Caught exit signal! Cleaning up..."
119
120     cleanup_abort
121
122     if [ $(jobs -p) ]; then
123         scottyerror TERMinating remaining child processes...
124         kill $(jobs -p)
125     fi
126     deleteLock
127     exit
128 }
129
130 function prepare {
131     scottyinfo "No prepare function was defined."
132 }
133
134 function _prepare {
135     prepare
136 }
137
138 function cleanup_normal {
139     scottyinfo "No cleanup_normal function was defined."
140 }
141
142 function _cleanup_normal {
143     cleanup_normal
144 }
145
146 function backmeupscotty {
147     while getopts "qn:" opt; do
148         case $opt in
149             q)
150                 exec > /dev/null
151                 ;;
152             n)
153                 BACKUP_RUNEVERYNTHDAY=$OPTARG
154                 ;;
155         esac
156     done
157
158     if ! isIncompleteOrNthDay; then
159         scottyinfo "This is not the nth day and no incomplete backup exists."
160         exit 0
161     fi
162
163     trap _cleanup_abort EXIT
164
165     _prepare
166     scottysync
167     _cleanup_normal
168
169     trap deleteLock EXIT
170 }
171
172 if ! mkdir /tmp/$(basename $0).lock; then
173     scottyerror "Another instance of $(basename $0) is still running!"
174     exit 1
175 else
176     trap deleteLock EXIT
177 fi