-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrsync_snap.sh
executable file
·139 lines (109 loc) · 3.83 KB
/
rsync_snap.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/bin/bash
#
# rsync_snap.sh creates rsync snapshot backups (using hardlinks) of remote servers
#
lockfile -r 0 /tmp/.rsync_snap.lck || { echo "ERROR: rsync_snap is already running"; exit 1; }
# read config
test -e ~/.rsync_snap.conf || { echo "ERROR: missing config file"; exit 1; }
declare -A SOURCES
declare -A PRE_SCRIPT
declare -A POST_SCRIPT
source ~/.rsync_snap.conf
test -d $DEST || { echo $DEST does not exist; exit 1; }
# create log & status file
test -e $LOG || { touch $LOG; chmod 600 $LOG; }
test -e /var/tmp/.rsync_snap.status || touch /var/tmp/.rsync_snap.status
STATUS=0
TS=$(date +%Y%m%d_%H%M)
TS_SECS=$(date +%s)
# disable wildcard expansion
set -f
# concatenate excludes from config
EXCL_ARGS=""
for PATTERN in $EXCLUDE; do
EXCL_ARGS="$EXCL_ARGS --exclude '$PATTERN'"
done
# run rsync
echo "$(date -R) *** starting rsync_snap" >> $LOG
for HOST in "${!SOURCES[@]}"; do
echo "$(date -R) [$HOST] processing" >> $LOG
# setup environment
RSYNC="rsync -ahix -zz --noatime --numeric-ids --outbuf=N --relative --stats -e 'ssh -i/root/.ssh/snapbackup_id_ed25519 -caes128-ctr -oStrictHostKeyChecking=accept-new -oBatchMode=yes' \
--exclude '*/.ansible/' \
--exclude '*/.cache/' \
--exclude '*/.snapshots/' \
--exclude '/dev/' \
--exclude '/media/' \
--exclude '/mnt/' \
--exclude '/proc/' \
--exclude '/run/' \
--exclude '/sys/' \
--exclude '/tmp/' \
--exclude '/var/cache/' \
--exclude '/var/run/' \
--exclude '/var/swap' \
--exclude '/var/tmp/' \
$EXCL_ARGS \
"
BACKUP_HOST="$DEST/${HOST%%.*}"
BACKUP_DEST="$BACKUP_HOST/$TS"
BACKUP_LATEST="$BACKUP_HOST/latest"
# append link-dest to rsync
if [ -e $BACKUP_LATEST ]; then
RSYNC="$RSYNC --link-dest=$BACKUP_LATEST"
LAT="$(basename $(readlink -f $BACKUP_LATEST))"
AGE=$(expr $TS_SECS - $(date -r $BACKUP_LATEST +%s))
echo "$(date -R) [$HOST] latest snapshot is $LAT ($AGE seconds old)" >> $LOG
if [ "$AGE" -lt "$AGE_MIN" ]; then
echo "$(date -R) [$HOST] skipping, snapshot less than $AGE_MIN seconds old" >> $LOG
continue
fi
else
echo "$(date -R) [$HOST] no previous snapshot found, this will be a full backup" >> $LOG
fi
# append paths to command
for p in ${SOURCES[$HOST]}; do
RSYNC="$RSYNC $HOST:$p/"
done
# append destination to command
RSYNC="$RSYNC $BACKUP_DEST/"
if [ ! -z "${PRE_SCRIPT[$HOST]}" ]; then
echo "$(date -R) [$HOST] running pre-script ${PRE_SCRIPT[$HOST]}" >> $LOG
eval ${PRE_SCRIPT[$HOST]} >> $LOG 2>&1
fi
# if pre-script ok
if [ $? -eq 0 ]; then
echo "$(date -R) [$HOST] backing up to $BACKUP_DEST" >> $LOG
mkdir -p $BACKUP_DEST
echo "+ $RSYNC" >> $LOG
eval $RSYNC >> $LOG 2>&1
ec=$?
echo "ec: $ec" >> $LOG
# if backup was successful, do some cleaning
if [ $ec -eq 0 ] || [ $ec -eq 24 ]; then
echo "$(date -R) [$HOST] backup successful, updating latest link" >> $LOG
touch $BACKUP_DEST
rm -f $BACKUP_LATEST
ln -rs $BACKUP_DEST $BACKUP_LATEST
echo "$(date -R) [$HOST] pruning snapshots older than $KEEP_DAYS days" >> $LOG
find $BACKUP_HOST/ -mindepth 1 -maxdepth 1 -type d -mtime +$KEEP_DAYS -regextype posix-extended -regex '.*/[0-9]{8}_[0-9]{4}$' -exec rm -r "{}" \; >> $LOG 2>&1
else
echo "$(date -R) [$HOST] rsync failed" >> $LOG
STATUS=1
rmdir $BACKUP_DEST
fi
if [ ! -z "${POST_SCRIPT[$HOST]}" ]; then
echo "$(date -R) [$HOST] running post-script ${POST_SCRIPT[$HOST]}" >> $LOG
eval ${POST_SCRIPT[$HOST]} >> $LOG 2>&1
fi
else
echo "$(date -R) [$HOST] pre-script failed, aborting" >> $LOG
STATUS=1
fi
done
test -f /var/tmp/.rsync_snap.status && echo $STATUS > /var/tmp/.rsync_snap.status
if [ $STATUS -eq 0 ]; then
touch /var/tmp/.rsync_snap.last
fi
rm -f /tmp/.rsync_snap.lck
echo "$(date -R) *** script completed" >> $LOG