Add duplicity output line by line instead of with a whole at one time. Should help...
[matthijs/upstream/backupninja.git] / handlers / dup.in
1 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
2 # vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
3 #
4 # duplicity script for backupninja
5 # requires duplicity
6 #
7
8 getconf options
9 getconf testconnect yes
10 getconf nicelevel 0
11 getconf tmpdir
12
13 setsection gpg
14 getconf password
15 getconf sign no
16 getconf encryptkey
17 getconf signkey
18
19 setsection source
20 getconf include
21 getconf vsnames all
22 getconf vsinclude
23 getconf exclude
24
25 setsection dest
26 getconf incremental yes
27 getconf keep 60
28 getconf desturl
29 getconf sshoptions
30 getconf bandwidthlimit 0
31 getconf desthost
32 getconf destdir
33 getconf destuser
34 destdir=${destdir%/}
35
36 ### SANITY CHECKS ##############################################################
37
38 [ -n "$desturl" -o -n "$destdir" ]  || fatal "The destination directory (destdir) must be set when desturl is not used."
39 [ -n "$include" -o -n "$vsinclude" ]  || fatal "No source includes specified"
40 [ -n "$password" ] || fatal "The password option must be set."
41
42 ### VServers
43 # If vservers are configured, check that the ones listed in $vsnames do exist.
44 local usevserver=no
45 if [ $vservers_are_available = yes ]; then
46    if [ "$vsnames" = all ]; then
47       vsnames="$found_vservers"
48    else
49       if ! vservers_exist "$vsnames" ; then
50             fatal "At least one of the vservers listed in vsnames ($vsnames) does not exist."
51       fi
52    fi
53    if [ -n "$vsinclude" ]; then
54       info "Using vservers '$vsnames'"
55       usevserver=yes
56    fi
57 else
58    [ -z "$vsinclude" ] || warning 'vservers support disabled in backupninja.conf, vsincludes configuration lines will be ignored'
59 fi
60
61 ### See if we can login on $desthost
62 if [ "$testconnect" == "yes" ]; then
63    if [ -n "$desturl" ]; then
64       warning 'testconnect can not be used when desturl is set'
65    else
66       debug "ssh $sshoptions -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'"
67       if [ ! $test ]; then
68          result=`ssh $sshoptions -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'`
69          if [ "$result" != "1" ]; then
70             fatal "Can't connect to $desthost as $destuser."
71          else
72             debug "Connected to $desthost as $destuser successfully"
73          fi
74       fi
75    fi
76 fi
77
78 ### COMMAND-LINE MANGLING ######################################################
79
80 ### initialize $execstr*
81 execstr_command=
82 execstr_options="$options --no-print-statistics"
83 execstr_source=
84 if [ -n "$desturl" ]; then
85    [ -z "$destuser" ] || warning 'the configured destuser is ignored since desturl is set'
86    [ -z "$desthost" ] || warning 'the configured desthost is ignored since desturl is set'
87    [ -z "$destdir" ] || warning 'the configured destdir is ignored since desturl is set'
88    execstr_serverpart="$desturl"
89 else
90    execstr_serverpart="scp://$destuser@$desthost/$destdir"
91 fi
92
93 ### duplicity version
94 duplicity_version="`duplicity --version | @AWK@ '{print $2}'`"
95 duplicity_major="`echo $duplicity_version | @AWK@ -F '.' '{print $1}'`"
96 duplicity_minor="`echo $duplicity_version | @AWK@ -F '.' '{print $2}'`"
97 duplicity_sub="`echo $duplicity_version | @AWK@ -F '.' '{print $3}'`"
98
99 ### ssh/scp/sftp options
100 # 1. duplicity >= 0.4.2 needs --sftp-command
101 #    (NB: sftp does not support the -l option)
102 # 2. duplicity 0.4.3 to 0.4.9 replace --ssh-command with --ssh-options, which is
103 #    passed to scp and sftp commands by duplicity. We don't use it: since this
104 #    version does not use the ssh command anymore, we keep compatibility with
105 #    our previous config files by passing $sshoptions to --scp-command and
106 #    --sftp-command ourselves
107
108 scpoptions="$sshoptions"
109 if [ "$bandwidthlimit" != 0 ]; then
110    [ -z "$desturl" ] || warning 'The bandwidthlimit option is not used when desturl is set.'
111    scpoptions="$scpoptions -l $bandwidthlimit"
112 fi
113
114 # < 0.4.2 : only uses ssh and scp
115 if [ "$duplicity_major" -le 0 -a "$duplicity_minor" -le 4 -a "$duplicity_sub" -lt 2 ]; then
116    execstr_options="${execstr_options} --scp-command 'scp $scpoptions' --ssh-command 'ssh $sshoptions'"
117 # >= 0.4.2 : also uses sftp, --sftp-command option is now supported
118 else
119    sftpoptions="$sshoptions"
120    # == 0.4.2 : uses ssh, scp and sftp
121    if [ "$duplicity_major" -eq 0 -a "$duplicity_minor" -eq 4 -a "$duplicity_sub" -eq 2 ]; then
122       execstr_options="${execstr_options} --scp-command 'scp $scpoptions' --sftp-command 'sftp $sftpoptions' --ssh-command 'ssh $sshoptions'"
123    # >= 0.4.3 : uses only scp and sftp, --ssh-command option is not supported anymore
124    else
125       execstr_options="${execstr_options} --scp-command 'scp $scpoptions' --sftp-command 'sftp $sftpoptions'"
126    fi
127 fi
128
129 ### Symmetric or asymmetric (public/private key pair) encryption
130 if [ -n "$encryptkey" ]; then
131    execstr_options="${execstr_options} --encrypt-key $encryptkey"
132    debug "Data will be encrypted with the GnuPG key $encryptkey."
133 else
134    debug "Data will be encrypted using symmetric encryption."
135 fi
136
137 ### Data signing (or not)
138 if [ "$sign" == yes ]; then
139    # duplicity is not able to sign data when using symmetric encryption
140    [ -n "$encryptkey" ] || fatal "The encryptkey option must be set when signing."
141    # if needed, initialize signkey to a value that is not empty (checked above)
142    [ -n "$signkey" ] || signkey="$encryptkey"
143    execstr_options="${execstr_options} --sign-key $signkey"
144    debug "Data will be signed will the GnuPG key $signkey."
145 else
146    debug "Data won't be signed."
147 fi
148
149 ### Incremental or full backup mode
150 # If incremental==yes, use the default duplicity behaviour: perform an
151 # incremental backup if old signatures can be found, else switch to
152 # full backup.
153 # If incremental==no, force a full backup anyway.
154 if [ "$incremental" == "no" ]; then
155    # before 0.4.4, full was an option and not a command
156    if [ "$duplicity_major" -le 0 -a "$duplicity_minor" -le 4 -a "$duplicity_sub" -lt 4 ]; then
157       execstr_options="${execstr_options} --full"
158    else
159       execstr_command="full"
160    fi
161 fi
162
163 ### Temporary directory
164 precmd=
165 if [ -n "$tmpdir" ]; then
166    if [ ! -d "$tmpdir" ]; then
167       info "Temporary directory ($tmpdir) does not exist, creating it."
168       mkdir -p "$tmpdir"
169       [ $? -eq 0 ] || fatal "Could not create temporary directory ($tmpdir)."
170       chmod 0700 "$tmpdir"
171    fi
172    info "Using $tmpdir as TMPDIR"
173    precmd="${precmd}TMPDIR=$tmpdir "
174 fi
175
176 ### Cleanup old backup sets (or not)
177 if [ "$keep" != "yes" ]; then
178    if [ "`echo $keep | tr -d 0-9`" == "" ]; then
179       keep="${keep}D"
180    fi
181    # before 0.4.4, remove-older-than was an option and not a command
182    if [ "$duplicity_major" -le 0 -a "$duplicity_minor" -le 4 -a "$duplicity_sub" -lt 4 ]; then
183       execstr_options="${execstr_options} --remove-older-than $keep"
184    fi
185 fi
186
187 ### Source
188
189 set -o noglob
190
191 # excludes
192 for i in $exclude; do
193    str="${i//__star__/*}"
194    execstr_source="${execstr_source} --exclude '$str'"
195 done
196
197 # includes
198 for i in $include; do
199    [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'"
200    str="${i//__star__/*}"
201    execstr_source="${execstr_source} --include '$str'"
202 done
203
204 # vsincludes
205 if [ $usevserver = yes ]; then
206    for vserver in $vsnames; do
207       for vi in $vsinclude; do
208          str="${vi//__star__/*}"
209          str="$VROOTDIR/$vserver$str"
210          execstr_source="${execstr_source} --include '$str'"
211       done
212    done
213 fi
214
215 set +o noglob
216
217 ### EXECUTE ####################################################################
218
219 execstr_source=${execstr_source//\\*/\\\\\\*}
220
221 ### Cleanup commands (duplicity >= 0.4.4)
222
223 # cleanup
224 if [ "$duplicity_major" -ge 0 -a "$duplicity_minor" -ge 4 -a "$duplicity_sub" -ge 4 ]; then
225    debug "$precmd duplicity cleanup --force $execstr_options $execstr_serverpart"
226    if [ ! $test ]; then
227       export PASSPHRASE=$password
228       output=`nice -n $nicelevel \
229          su -c \
230          "$precmd duplicity cleanup --force $execstr_options $execstr_serverpart 2>&1"`
231       exit_code=$?
232       if [ $exit_code -eq 0 ]; then
233          debug $output
234          info "Duplicity cleanup finished successfully."
235       else
236          debug $output
237          warning "Duplicity cleanup failed."
238       fi
239    fi
240 fi
241
242 # remove-older-than
243 if [ "$keep" != "yes" ]; then
244    if [ "$duplicity_major" -ge 0 -a "$duplicity_minor" -ge 4 -a "$duplicity_sub" -ge 4 ]; then
245       debug "$precmd duplicity remove-older-than $keep --force $execstr_options $execstr_serverpart"
246       if [ ! $test ]; then
247          export PASSPHRASE=$password
248          output=`nice -n $nicelevel \
249                    su -c \
250                       "$precmd duplicity remove-older-than $keep --force $execstr_options $execstr_serverpart 2>&1"`
251          exit_code=$?
252          if [ $exit_code -eq 0 ]; then
253             debug $output
254             info "Duplicity remove-older-than finished successfully."
255          else
256             debug $output
257             warning "Duplicity remove-older-than failed."
258          fi
259       fi
260    fi
261 fi
262
263 ### Backup command
264 debug "$precmd duplicity $execstr_command $execstr_options $execstr_source --exclude '**' / $execstr_serverpart"
265 if [ ! $test ]; then
266    outputfile=`maketemp backupout`
267    export PASSPHRASE=$password
268    output=`nice -n $nicelevel \
269              su -c \
270                 "$precmd duplicity $execstr_command $execstr_options $execstr_source --exclude '**' / $execstr_serverpart >$outputfile 2>&1"`
271    exit_code=$?
272    debug $output
273    cat $outputfile | (while read output ; do
274                          debug $output
275                       done
276    )
277    if [ $exit_code -eq 0 ]; then
278       info "Duplicity finished successfully."
279    else
280       fatal "Duplicity failed."
281    fi
282    rm $outputfile
283 fi
284
285 return 0