2 # backupninja handler for incremental backups using rsync and hardlinks
3 # feedback: rhatto at riseup.net
5 # rsync handler is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; either version 2 of the License, or any later version.
9 # rsync handler is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 # You should have received a copy of the GNU General Public License along with
15 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 # Place - Suite 330, Boston, MA 02111-1307, USA
21 # - http://www.mikerubel.org/computers/rsync_snapshots/
22 # - rsnap handler by paulv at bikkel.org
23 # - maildir handler from backupninja
29 # log = rsync log file
30 # partition = partition where the backup lives
31 # fscheck = set to 1 if fsck should run on $partition after the backup is made
32 # read_only = set to 1 if $partition is mounted read-only
33 # mountpoint = backup partition mountpoint or backup main folder (either local or remote)
34 # backupdir = folder relative do $mountpoint where the backup should be stored (local or remote)
35 # format = specify backup storage format: short, long or mirror (i.e, no rotations)
36 # days = for short storage format, specify the number of backup increments (min = 5)
37 # keepdaily = for long storage format, specify the number of daily backup increments
38 # keepweekly = for long storage format, specify the number of weekly backup increments
39 # keepmonthly = for long storage format, specify the number of monthly backup increments
40 # lockfile = lockfile to be kept during backup execution
41 # nicelevel = rsync command nice level
42 # enable_mv_timestamp_bug = set to "yes" if your system isnt handling timestamps correctly
44 # multiconnection = set to "yes" if you want to use multiconnection ssh support
47 # from = local or remote
48 # host = source hostname or ip, if remote backup
49 # port = remote port number (remote source only)
50 # user = remote user name (remote source only)
51 # testconnect = when "yes", test the connection for a remote source before backup
52 # include = include folder on backup
53 # exclude = exclude folder on backup
54 # ssh = ssh command line (remote source only)
55 # protocol = ssh or rsync (remote source only)
56 # rsync = rsync program
57 # rsync_options = rsync command options
58 # exclude_vserver = vserver-name (valid only if vservers = yes on backupninja.conf)
59 # numericids = when set to 1, use numeric ids instead of user/group mappings on rsync
60 # compress = if set to 1, compress data on rsync (remote source only)
61 # bandwidthlimit = set a badnwidth limit in kbps (remote source only)
62 # remote_rsync = remote rsync program (remote source only)
63 # id_file = ssh key file (remote source only)
64 # batch = set to "yes" to rsync use a batch file as source
65 # batchbase = folder where the batch file is located
66 # filelist = set yes if you want rsync to use a file list source
67 # filelistbase = folder where the file list is placed
70 # dest = backup destination type (local or remote)
71 # testconnect = when "yes", test the connection for a remote source before backup
72 # ssh = ssh command line (remote dest only)
73 # protocol = ssh or rsync (remote dest only)
74 # numericids = when set to 1, use numeric ids instead of user/group mappings on rsync
75 # compress = if set to 1, compress data on rsync (remote source only)
76 # host = destination host name (remote destination only)
77 # port = remote port number (remote destination only)
78 # user = remote user name (remote destination only)
79 # id_file = ssh key file (remote destination only)
80 # bandwidthlimit = set a badnwidth limit in kbps (remote destination only)
81 # remote_rsync = remote rsync program (remote dest only)
82 # batch = set to "yes" to rsync write a batch file from the changes
83 # batchbase = folder where the batch file should be written
84 # fakesuper = set to yes so rsync use the --fake-super flag (remote destination only)
87 # initscripts = absolute path where scripts are located
88 # service = script name to be stoped at the begining of the backup and started at its end
90 # You can also specify some system comands if you don't want the default system values:
95 # touch = touch command
99 # You dont need to manually specify vservers using "include = /vservers".
100 # They are automatically backuped if vserver is set to "yes" on you backupninja.conf.
105 # 20090329 - rhatto at riseup.net
107 # - Added support for:
108 # - Remote destinations
109 # - Long rotation format similar to maildir handler
110 # - Batch files through --read-batch and --write-batch
111 # - Custom file list using --files-from
112 # - SSH persistent connection using ControlMaster
113 # - The rsync:// protocol
114 # - Metadata folder for each backup folder
115 # - General refactoring
119 # function definitions
121 function eval_config {
135 getconf log /var/log/backup/rsync.log
145 getconf keepmonthly 1
148 getconf enable_mv_timestamp_bug no
150 getconf multiconnection no
157 getconf rsync_options "-av --delete --recursive"
159 if [ "$from" == "remote" ]; then
160 getconf testconnect no
165 if [ "$protocol" == "ssh" ]; then
166 # sshd default listen port
169 # rsyncd default listen port
174 getconf bandwidthlimit
175 getconf remote_rsync rsync
176 getconf id_file /root/.ssh/id_dsa
181 if [ "$batch" == "yes" ]; then
183 if [ ! -z "$batchbase" ]; then
192 getconf exclude_vserver
202 if [ "$dest" == "remote" ]; then
203 getconf testconnect no
208 if [ "$protocol" == "ssh" ]; then
209 # sshd default listen port
212 # rsyncd default listen port
217 getconf bandwidthlimit
218 getconf remote_rsync rsync
219 getconf id_file /root/.ssh/id_dsa
224 if [ "$batch" != "yes" ]; then
226 if [ "$batch" == "yes" ]; then
228 if [ ! -z "$batchbase" ]; then
240 getconf initscripts /etc/init.d
245 if [ "$dest" != "local" ] && [ "$from" == "remote" ]; then
246 fatal "When source is remote, destination should be local."
250 if [ "$from" != "local" ] && [ "$from" != "remote" ]; then
251 fatal "Invalid source $from"
255 backupdir="$mountpoint/$backupdir"
257 if [ "$dest" == "local" ] && [ ! -d "$backupdir" ]; then
258 error "Backupdir $backupdir does not exist"
262 if [ ! -z "$log" ]; then
263 mkdir -p `dirname $log`
266 if [ "$format" == "short" ]; then
267 if [ -z "$days" ]; then
270 keep="`echo $days - 1 | bc -l`"
274 if [ ! -z "$nicelevel" ]; then
275 nice="nice -n $nicelevel"
280 ssh_cmd="ssh -T -o PasswordAuthentication=no $host -p $port -l $user -i $id_file"
282 if [ "$from" == "remote" ] || [ "$dest" == "remote" ]; then
283 if [ "$testconnect" == "yes" ] && [ "$protocol" == "ssh" ]; then
284 test_connect $host $port $user $id_file
288 if [ "$multiconnection" == "yes" ]; then
289 ssh_cmd="$ssh_cmd -S $tmp/%r@%h:%p"
292 if [ $enable_mv_timestamp_bug == "yes" ]; then
296 for path in $exclude; do
297 excludes="$excludes --exclude=$path"
302 function rotate_short {
307 local metadata="`dirname $folder`/metadata"
309 if [[ "$keep" -lt 4 ]]; then
310 error "Rotate: minimum of 4 rotations"
314 if [ -d $folder.$keep ]; then
315 $nice $mv /$folder.$keep /$folder.tmp
318 for ((n=`echo "$keep - 1" | bc`; n >= 0; n--)); do
319 if [ -d $folder.$n ]; then
320 dest=`echo "$n + 1" | bc`
321 $nice $mv /$folder.$n /$folder.$dest
322 $touch /$folder.$dest
323 mkdir -p $metadata/`basename $folder`.$dest
324 date +%c%n%s > $metadata/`basename $folder`.$dest/rotated
328 if [ -d $folder.tmp ]; then
329 $nice $mv /$folder.tmp /$folder.0
332 if [ -d $folder.1 ]; then
333 $nice $cp -alf /$folder.1/. /$folder.0
338 function rotate_short_remote {
341 local metadata="`dirname $folder`/metadata"
344 if [[ "$2" -lt 4 ]]; then
345 error "Rotate: minimum of 4 rotations"
351 ##### BEGIN REMOTE SCRIPT #####
353 if [ -d $folder.$keep ]; then
354 $nice mv /$folder.$keep /$folder.tmp
357 for ((n=$(($keep - 1)); n >= 0; n--)); do
358 if [ -d $folder.\$n ]; then
360 $nice mv /$folder.\$n /$folder.\$dest
361 touch /$folder.\$dest
362 mkdir -p $metadata/`basename $folder`.\$dest
363 date +%c%n%s > $metadata/`basename $folder`.\$dest/rotated
367 if [ -d $folder.tmp ]; then
368 $nice mv /$folder.tmp /$folder.0
371 if [ -d $folder.1 ]; then
372 $nice $cp -alf /$folder.1/. /$folder.0
374 ##### END REMOTE SCRIPT #######
376 ) | (while read a; do passthru $a; done)
380 function rotate_long {
384 seconds_weekly=604800
385 seconds_monthly=2628000
387 keepweekly=$keepweekly
388 keepmonthly=$keepmonthly
393 if [ ! -d "$backuproot" ]; then
394 echo "Debug: skipping rotate of $backuproot as it doesn't exist."
398 for rottype in daily weekly monthly; do
399 seconds=$((seconds_${rottype}))
401 dir="$backuproot/$rottype"
402 metadata="$backuproot/metadata/$rottype.1"
404 if [ ! -d $dir.1 ]; then
405 echo "Debug: $dir.1 does not exist, skipping."
407 elif [ ! -f $metadata/created ] && [ ! -f $metadata/rotated ]; then
408 echo "Warning: metadata does not exist for $dir.1. This backup may be only partially completed. Skipping rotation."
412 # Rotate the current list of backups, if we can.
413 oldest=`find $backuproot -maxdepth 1 -type d -name $rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1`
414 [ "$oldest" == "" ] && oldest=0
415 for (( i=$oldest; i > 0; i-- )); do
416 if [ -d $dir.$i ]; then
417 if [ -f $metadata/created ]; then
418 created=`tail -1 $metadata/created`
419 elif [ -f $metadata/rotated ]; then
420 created=`tail -1 $metadata/rotated`
424 cutoff_time=$(( now - (seconds*(i-1)) ))
425 if [ ! $created -gt $cutoff_time ]; then
427 if [ ! -d $dir.$next ]; then
428 echo "Debug: $rottype.$i --> $rottype.$next"
429 $nice mv $dir.$i $dir.$next
430 mkdir -p $backuproot/metadata/$rottype.$next
431 date +%c%n%s > $backuproot/metadata/$rottype.$next/rotated
433 echo "Debug: skipping rotation of $dir.$i because $dir.$next already exists."
436 echo "Debug: skipping rotation of $dir.$i because it was created" $(( (now-created)/86400)) "days ago ("$(( (now-cutoff_time)/86400))" needed)."
443 if [ $keepweekly -gt 0 -a -d $backuproot/daily.$max -a ! -d $backuproot/weekly.1 ]; then
444 echo "Debug: daily.$max --> weekly.1"
445 $nice mv $backuproot/daily.$max $backuproot/weekly.1
446 mkdir -p $backuproot/metadata/weekly.1
447 date +%c%n%s > $backuproot/metadata/weekly.1/rotated
450 max=$((keepweekly+1))
451 if [ $keepmonthly -gt 0 -a -d $backuproot/weekly.$max -a ! -d $backuproot/monthly.1 ]; then
452 echo "Debug: weekly.$max --> monthly.1"
453 $nice mv $backuproot/weekly.$max $backuproot/monthly.1
454 mkdir -p $backuproot/metadata/monthly.1
455 date +%c%n%s > $backuproot/metadata/monthly.1/rotated
458 for rottype in daily weekly monthly; do
459 max=$((keep${rottype}+1))
460 dir="$backuproot/$rottype"
461 oldest=`find $backuproot -maxdepth 1 -type d -name $rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1`
462 [ "$oldest" == "" ] && oldest=0
463 # if we've rotated the last backup off the stack, remove it.
464 for (( i=$oldest; i >= $max; i-- )); do
465 if [ -d $dir.$i ]; then
466 if [ -d $backuproot/rotate.tmp ]; then
467 echo "Debug: removing rotate.tmp"
468 $nice rm -rf $backuproot/rotate.tmp
470 echo "Debug: moving $rottype.$i to rotate.tmp"
471 $nice mv $dir.$i $backuproot/rotate.tmp
478 function rotate_long_remote {
480 local backuproot="$1"
484 ##### BEGIN REMOTE SCRIPT #####
487 seconds_weekly=604800
488 seconds_monthly=2628000
490 keepweekly=$keepweekly
491 keepmonthly=$keepmonthly
494 if [ ! -d "$backuproot" ]; then
495 echo "Debug: skipping rotate of $backuproot as it doesn't exist."
499 for rottype in daily weekly monthly; do
500 seconds=\$((seconds_\${rottype}))
502 dir="$backuproot/\$rottype"
503 metadata="$backuproot/metadata/\$rottype.1"
505 if [ ! -d \$dir.1 ]; then
506 echo "Debug: \$dir.1 does not exist, skipping."
508 elif [ ! -f \$metadata/created ] && [ ! -f \$metadata/rotated ]; then
509 echo "Warning: metadata does not exist for \$dir.1. This backup may be only partially completed. Skipping rotation."
513 # Rotate the current list of backups, if we can.
514 oldest=\`find $backuproot -maxdepth 1 -type d -name \$rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1\`
515 [ "\$oldest" == "" ] && oldest=0
516 for (( i=\$oldest; i > 0; i-- )); do
517 if [ -d \$dir.\$i ]; then
518 if [ -f \$metadata/created ]; then
519 created=\`tail -1 \$metadata/created\`
520 elif [ -f \$metadata/rotated ]; then
521 created=\`tail -1 \$metadata/rotated\`
525 cutoff_time=\$(( now - (seconds*(i-1)) ))
526 if [ ! \$created -gt \$cutoff_time ]; then
528 if [ ! -d \$dir.\$next ]; then
529 echo "Debug: \$rottype.\$i --> \$rottype.\$next"
530 $nice mv \$dir.\$i \$dir.\$next
531 mkdir -p $backuproot/metadata/\$rottype.\$next
532 date +%c%n%s > $backuproot/metadata/\$rottype.\$next/rotated
534 echo "Debug: skipping rotation of \$dir.\$i because \$dir.\$next already exists."
537 echo "Debug: skipping rotation of \$dir.\$i because it was created" \$(( (now-created)/86400)) "days ago ("\$(( (now-cutoff_time)/86400))" needed)."
543 max=\$((keepdaily+1))
544 if [ \$keepweekly -gt 0 -a -d $backuproot/daily.\$max -a ! -d \$backuproot/weekly.1 ]; then
545 echo "Debug: daily.\$max --> weekly.1"
546 $nice mv $backuproot/daily.\$max $backuproot/weekly.1
547 mkdir -p $backuproot/metadata/weekly.1
548 date +%c%n%s > $backuproot/metadata/weekly.1/rotated
551 max=\$((keepweekly+1))
552 if [ \$keepmonthly -gt 0 -a -d $backuproot/weekly.\$max -a ! -d $backuproot/monthly.1 ]; then
553 echo "Debug: weekly.\$max --> monthly.1"
554 $nice mv $backuproot/weekly.\$max $backuproot/monthly.1
555 mkdir -p $backuproot/metadata/monthly.1
556 date +%c%n%s > $backuproot/metadata/monthly.1/rotated
559 for rottype in daily weekly monthly; do
560 max=\$((keep\${rottype}+1))
561 dir="$backuproot/\$rottype"
562 oldest=\`find $backuproot -maxdepth 1 -type d -name \$rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1\`
563 [ "\$oldest" == "" ] && oldest=0
564 # if we've rotated the last backup off the stack, remove it.
565 for (( i=\$oldest; i >= \$max; i-- )); do
566 if [ -d \$dir.\$i ]; then
567 if [ -d $backuproot/rotate.tmp ]; then
568 echo "Debug: removing rotate.tmp"
569 $nice rm -rf $backuproot/rotate.tmp
571 echo "Debug: moving \$rottype.\$i to rotate.tmp"
572 $nice mv \$dir.\$i $backuproot/rotate.tmp
576 ##### END REMOTE SCRIPT #######
578 ) | (while read a; do passthru $a; done)
582 function setup_long_dirs {
586 local dir="$destdir/$backuptype"
587 local tmpdir="$destdir/rotate.tmp"
588 local metadata="$destdir/metadata/$backuptype.1"
590 if [ ! -d $destdir ]; then
591 echo "Creating destination directory $destdir..."
595 if [ -d $dir.1 ]; then
596 if [ -f $metadata/created ]; then
597 echo "Warning: $dir.1 already exists. Overwriting contents."
599 echo "Warning: we seem to be resuming a partially written $dir.1"
602 if [ -d $tmpdir ]; then
605 echo "Fatal: could mv $destdir/rotate.tmp $dir.1 on host $host"
609 mkdir --parents $dir.1
611 echo "Fatal: could not create directory $dir.1 on host $host"
615 if [ -d $dir.2 ]; then
616 echo "Debug: update links $backuptype.2 --> $backuptype.1"
617 cp -alf $dir.2/. $dir.1
618 #if [ $? == 1 ]; then
619 # echo "Fatal: could not create hard links to $dir.1 on host $host"
624 [ -f $metadata/created ] && rm $metadata/created
625 [ -f $metadata/rotated ] && rm $metadata/rotated
629 function setup_long_dirs_remote {
633 local dir="$destdir/$backuptype"
634 local tmpdir="$destdir/rotate.tmp"
635 local metadata="$destdir/metadata/$backuptype.1"
639 ##### BEGIN REMOTE SCRIPT #####
640 if [ ! -d $destdir ]; then
641 echo "Creating destination directory $destdir on $host..."
645 if [ -d $dir.1 ]; then
646 if [ -f $metadata/created ]; then
647 echo "Warning: $dir.1 already exists. Overwriting contents."
649 echo "Warning: we seem to be resuming a partially written $dir.1"
652 if [ -d $tmpdir ]; then
654 if [ \$? == 1 ]; then
655 echo "Fatal: could mv $destdir/rotate.tmp $dir.1 on host $host"
659 mkdir --parents $dir.1
660 if [ \$? == 1 ]; then
661 echo "Fatal: could not create directory $dir.1 on host $host"
665 if [ -d $dir.2 ]; then
666 echo "Debug: update links $backuptype.2 --> $backuptype.1"
667 cp -alf $dir.2/. $dir.1
668 #if [ \$? == 1 ]; then
669 # echo "Fatal: could not create hard links to $dir.1 on host $host"
674 [ -f $metadata/created ] && rm $metadata/created
675 [ -f $metadata/rotated ] && rm $metadata/rotated
676 ##### END REMOTE SCRIPT #######
678 ) | (while read a; do passthru $a; done)
682 function move_files {
684 ref=$tmp/makesnapshot-mymv-$$;
692 function prepare_storage {
694 section="`basename $SECTION`"
696 if [ "$format" == "short" ]; then
699 info "Rotating $backupdir/$SECTION..."
700 echo "Rotating $backupdir/$SECTION..." >> $log
702 if [ "$dest" == "remote" ]; then
703 rotate_short_remote $backupdir/$SECTION/$section $keep
705 rotate_short $backupdir/$SECTION/$section $keep
706 if [ ! -d "$backupdir/$SECTION/$section.0" ]; then
707 mkdir -p $backupdir/$SECTION/$section.0
711 elif [ "$format" == "long" ]; then
713 if [ $keepdaily -gt 0 ]; then
715 elif [ $keepweekly -gt 0 ]; then
717 elif [ $keepmonthly -gt 0 ]; then
720 fatal "keeping no backups";
725 info "Rotating $backupdir/$SECTION/..."
726 echo "Rotating $backupdir/$SECTION/..." >> $log
728 if [ "$dest" == "remote" ]; then
729 rotate_long_remote $backupdir/$SECTION
730 setup_long_dirs_remote $backupdir/$SECTION $btype
732 rotate_long $backupdir/$SECTION
733 setup_long_dirs $backupdir/$SECTION $btype
736 elif [ "$format" == "mirror" ]; then
739 fatal "Invalid backup format $format"
747 if [ "$from" == "local" ]; then
749 elif [ "$from" == "remote" ]; then
750 if [ "$protocol" == "rsync" ]; then
751 orig="rsync://$user@$host:$port/$SECTION/"
753 orig="$user@$host:/$SECTION/"
761 if [ "$dest" == "local" ]; then
762 dest_path="$backupdir/$SECTION/$suffix/"
764 if [ "$protocol" == "rsync" ]; then
765 dest_path="rsync://$user@$host:$port/$backupdir/$SECTION/$suffix/"
767 dest_path="$user@$host:$backupdir/$SECTION/$suffix/"
773 function set_batch_mode {
775 local batch_file="$batchbase/$SECTION/$suffix"
777 if [ "$batch" == "read" ]; then
778 if [ -e "$batch_file" ]; then
781 batch_option="--read-batch=$batch_file"
783 fatal "Batch file not found: $batch_file"
786 elif [ "$batch" == "write" ]; then
787 mkdir -p `dirname $batch_file`
788 batch_option="--write-batch=$batch_file"
793 function update_metadata {
798 if [ "$dest" == "local" ]; then
799 metadata="`dirname $dest_path`/metadata/`basename $dest_path`"
801 date +%c%n%s > $metadata/created
802 $touch $backupdir/$SECTION/$suffix
804 folder="`echo $dest_path | cut -d : -f 2`"
805 metadata="`dirname $folder`/metadata/`basename $folder`"
809 ##### BEGIN REMOTE SCRIPT #####
811 date +%c%n%s > $metadata/created
812 ##### END REMOTE SCRIPT #######
814 ) | (while read a; do passthru $a; done)
820 function test_connect {
827 if [ -z "$host" ] || [ -z "$user" ]; then
828 fatal "Remote host or user not set"
832 debug "$ssh_cmd 'echo -n 1'"
833 result=`$ssh_cmd 'echo -n 1'`
835 if [ "$result" != "1" ]; then
836 fatal "Can't connect to $host as $user."
839 debug "Connected to $host successfully"
844 function set_lockfile {
846 if [ ! -z "$lockfile" ]; then
847 $touch $lockfile || warning "Could not create lockfile $lockfile"
852 function unset_lockfile {
854 if [ ! -z "$lockfile" ]; then
855 $rm $lockfile || warning "Could not remove lockfile $lockfile"
860 function set_filelist {
864 if [ "$filelist" == "yes" ]; then
865 if [ ! -z "$filelistbase" ]; then
866 if [ -e "$filelistbase/$SECTION/$suffix" ]; then
867 filelist_flag="--files-from=$filelistbase/$SECTION/$suffix"
869 warning "File list $filelistbase/$SECTION/$suffix not found."
872 warning "No filelistbase set."
878 function set_rsync_options {
880 if [ ! -z "$numericids" ]; then
881 rsync_options="$rsync_options --numeric-ids"
884 if [ "$from" == "local" ] || [ "$dest" == "local" ]; then
885 # rsync options for local sources or destinations
886 rsync_options="$rsync_options"
889 if [ "$from" == "remote" ] || [ "$dest" == "remote" ]; then
891 # rsync options for remote sources or destinations
893 if [ "$compress" == "1" ]; then
894 rsync_options="$rsync_options --compress"
897 if [ ! -z "$bandwidthlimit" ]; then
898 rsync_options="$rsync_options --bwlimit=$bandwidthlimit"
901 if [ "$fakesuper" == "yes" ]; then
902 remote_rsync="$remote_rsync --fake-super"
905 rsync_options=($rsync_options --rsync-path="$remote_rsync")
907 if [ "$protocol" == "ssh" ]; then
908 if [ ! -e "$id_file" ]; then
909 fatal "SSH Identity file $id_file not found"
912 debug RSYNC_RSH=\"$ssh_cmd\"
913 echo RSYNC_RSH=\"$ssh_cmd\" >> $log
924 function stop_services {
926 if [ ! -z "$service" ]; then
927 for daemon in $service; do
928 info "Stopping service $daemon..."
929 $initscripts/$daemon stop
935 function start_services {
939 if [ ! -z "$service" ]; then
940 for daemon in $service; do
941 info "Starting service $daemon..."
942 $initscripts/$daemon start
950 # mount backup destination folder as read-write
952 if [ "$dest" == "local" ]; then
953 if [ "$read_only" == "1" ] || [ "$read_only" == "yes" ]; then
954 if [ -d "$mountpoint" ]; then
955 mount -o remount,rw $mountpoint
957 error "Could not mount $mountpoint"
968 # remount backup destination as read-only
970 if [ "$dest" == "local" ]; then
971 if [ "$read_only" == "1" ] || [ "$read_only" == "yes" ]; then
972 mount -o remount,ro $mountpoint
980 # check partition for errors
982 if [ "$dest" == "local" ]; then
983 if [ "$fscheck" == "1" ] || [ "$fscheck" == "yes" ]; then
986 warning "Could not umount $mountpoint to run fsck"
988 $nice $fsck -v -y $partition >> $log
996 function include_vservers {
998 # add vservers to included folders
1000 if [ "$vservers_are_available" == "yes" ]; then
1002 # sane permission on backup
1003 mkdir -p $backupdir/$VROOTDIR
1004 chmod 000 $backupdir/$VROOTDIR
1006 for candidate in $found_vservers; do
1007 candidate="`basename $candidate`"
1008 found_excluded_vserver="0"
1009 for excluded_vserver in $exclude_vserver; do
1010 if [ "$excluded_vserver" == "$candidate" ]; then
1011 found_excluded_vserver="1"
1015 if [ "$found_excluded_vserver" == "0" ]; then
1016 include="$include $VROOTDIR/$candidate"
1023 function start_mux {
1025 if [ "$multiconnection" == "yes" ]; then
1026 debug "Starting master ssh connection"
1027 $ssh_cmd -M sleep 1d &
1035 if [ "$multiconnection" == "yes" ]; then
1036 debug "Stopping master ssh connection"
1037 $ssh_cmd pkill sleep
1042 # the backup procedure
1051 echo "Starting backup at `date`" >> $log
1053 for SECTION in $include; do
1061 info "Syncing $SECTION on $dest_path..."
1062 debug $nice $rsync "${rsync_options[@]}" $filelist_flag $excludes $batch_option $orig $dest_path
1063 $nice $rsync "${rsync_options[@]}" $filelist_flag $excludes $batch_option $orig $dest_path >> $log
1065 if [ "$?" != "0" ]; then
1066 warning "Rsync error when trying to transfer $SECTION"
1079 echo "Finnishing backup at `date`" >> $log