]> git.llucax.com Git - software/bacap.git/blob - bacap
Fail if the BACKUP_DIR doesn't exist
[software/bacap.git] / bacap
1 #!/bin/bash
2
3 #_INCLUDE_START_
4 # Default config values
5
6 # Be verbose
7 VERBOSE=1
8
9 # Be extra verbose
10 DEBUG=0
11
12 # Don't actually do anything, just print the commands
13 DRY_RUN=0
14
15 # Force synchronization, even when the target already exist
16 FORCE_SYNC=0
17
18 # Log file (if empty, print to stdout/err)
19 LOG_FILE=
20
21 # Where to find the configuration of the hosts to backup
22 CONFIG_PATH=/etc/bacap/hosts
23
24 # Name of the local host (so no ssh would be used with this host)
25 LOCALHOST=$HOSTNAME
26
27 # Where to put the backups
28 BACKUP_PATH=/backup
29
30 # Date format used for backed up directories (passed to the date command)
31 DATE_FMT="%Y-%m-%d"
32
33 # Ping remote hosts to check if they are up (set to 0 if your hosts don't
34 # reply to ICMP pings).
35 PING_CHECK=1
36
37 # rsync flags to use
38 RSYNC_FLAGS="-aAHSXx --numeric-ids"
39
40 # rsync flags to use when in verbose mode
41 RSYNC_VERBOSE_FLAGS="-v --stats"
42
43 # rsync remote shell to use
44 RSYNC_RSH="ssh"
45
46 #_INCLUDE_END_
47
48 SCRIPT_DIR=$(dirname `readlink -f $0`)
49 BACAPRC=$1
50
51 # Load configuration files
52 load_config() {
53         extra_config=$1
54         source "/etc/bacaprc" 2> /dev/null
55         source "/etc/bacap/bacaprc" 2> /dev/null
56         source "$SCRIPT_DIR/bacaprc" 2> /dev/null
57         test -n "$BACAPRC" && source "$BACAPRC"
58         test -n "$extra_config" && source "$1" 2> /dev/null
59
60         run=
61         [ $DRY_RUN -eq 1 ] &&
62                 run=echo
63         [ $VERBOSE -eq 1 ] &&
64                 RSYNC_FLAGS="$RSYNC_FLAGS $RSYNC_VERBOSE_FLAGS"
65         [ $DEBUG -eq 1 ] &&
66                 V=-v
67         exec 3>&2
68         [ -n "$LOG_FILE" ] &&
69                 exec 1>>"$LOG_FILE" &&
70                 exec 2>>"$LOG_FILE"
71
72         export RSYNC_RSH
73 }
74
75 error() {
76         echo "$@" >&3
77 }
78
79 log() {
80         [ $VERBOSE -eq 1 ] &&
81                 echo "$@"
82 }
83
84 logerr() {
85         echo "$@" >&2
86 }
87
88 ping_host() {
89         ping -c1 "$1" > /dev/null 2>&1
90 }
91
92 load_config
93
94 if ! test -d "$BACKUP_PATH"
95 then
96         error "BACKUP_PATH=$BACKUP_PATH doesn't exist!"
97         exit 1
98 fi
99
100 date=`date "+$DATE_FMT"`
101 log
102 log
103 log "========================================================================="
104 log "Starting backup for $date at `date '+%Y-%m-%d %H:%M:%S'`"
105 log "========================================================================="
106 ret=0
107 for host_path in "$CONFIG_PATH"/*
108 do
109         saved_ret=$ret
110         # Load default config and override config if correspond
111         load_config "$host_path/bacaprc"
112         host=`basename "$host_path"`
113         host_backup_path="$BACKUP_PATH/$host"
114         mkdir -p $host_backup_path
115         dst="$BACKUP_PATH/$host/$date"
116         src=`cat "$host_path/paths"`
117         [ "$host" != "$LOCALHOST" ] &&
118                 src=`awk "{print \"$host:\"\\$1}" "$host_path/paths"`
119         exclude="$host_path/excludes"
120         include="$host_path/includes"
121         current_link="$host_backup_path/current"
122         current_dir="$host_backup_path/`readlink \"$current_link\"`"
123         extra_flags=
124         log "-----------------------------------------------------------------"
125         log "Backup for host $host started at `date '+%Y-%m-%d %H:%M:%S'`"
126         log "-----------------------------------------------------------------"
127         log "Source:      $src"
128         log "Destination: $dst"
129         log "Last:        $current_dir"
130         log
131         [ -d "$dst" ] && [ "$FORCE_SYNC" -ne 1 ] &&
132                 logerr "$dst already exists, skipping..." &&
133                 continue
134         [ "$PING_CHECK" -eq 1 ] && ! ping_host $host &&
135                 logerr "$host is down, skipping..." &&
136                 continue
137         [ -r "$exclude" ] &&
138                 extra_flags="--exclude-from=$exclude"
139         [ -r "$include" ] &&
140                 extra_flags="$extra_flags --include-from=$include"
141         log "Running rsync..."
142         $run rsync $RSYNC_FLAGS $extra_flags \
143                                 --link-dest="$current_dir" $src "$dst/"
144         rsync_ret=$?
145         case $rsync_ret in
146                 0)
147                         # Normal return
148                         ;;
149                 24)
150                         # Ignore error 24 from rsync ("Partial transfer due to
151                         # vanished source files") which is somewhat expected
152                         # since we don't do a snapshot
153                         ;;
154                 *)
155                         # Any other error is important enough
156                         ret=$(($ret+1))
157                         ;;
158         esac
159
160         if [ $ret -eq $saved_ret ]
161         then
162                 # Only move current if rsync did not fail, to avoid dangling
163                 # symlinks
164                 log "Moving current..."
165                 $run rm -f $V "$current_link" ||
166                 ret=$(($ret+1))
167                 $run ln -s $V "$date" "$current_link" ||
168                 ret=$(($ret+1))
169         else
170                 ERROR_HOSTS="$ERROR_HOSTS $host"
171         fi
172 done
173
174 log "========================================================================="
175 log "Backup for $date finished at `date '+%Y-%m-%d %H:%M:%S'`"
176 log "========================================================================="
177
178 if [ $ret -ne 0 ]
179 then
180         error
181         error "There were some errors when running the backup on: $ERROR_HOSTS"
182         error
183         if [ -n "$LOG_FILE" ]
184         then
185                 error "Please take a look at the log: $LOG_FILE"
186                 error
187         fi
188 fi
189
190 exit $ret
191