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