1 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
2 # vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
4 # backupninja handler for incremental backups using rsync and hardlinks
5 # feedback: rhatto at riseup.net
7 # rsync handler is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by the Free
9 # Software Foundation; either version 2 of the License, or any later version.
11 # rsync handler is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 # You should have received a copy of the GNU General Public License along with
17 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
18 # Place - Suite 330, Boston, MA 02111-1307, USA
23 # - http://www.mikerubel.org/computers/rsync_snapshots/
24 # - rsnap handler by paulv at bikkel.org
25 # - maildir handler from backupninja
31 # log = rsync log file
32 # partition = partition where the backup lives
33 # fscheck = set to 1 if fsck should run on $partition after the backup is made
34 # read_only = set to 1 if $partition is mounted read-only
35 # mountpoint = backup partition mountpoint or backup main folder (either local or remote)
36 # backupdir = folder relative do $mountpoint where the backup should be stored (local or remote)
37 # format = specify backup storage format: short, long or mirror (i.e, no rotations)
38 # days = for short storage format, specify the number of backup increments (min = 5)
39 # keepdaily = for long storage format, specify the number of daily backup increments
40 # keepweekly = for long storage format, specify the number of weekly backup increments
41 # keepmonthly = for long storage format, specify the number of monthly backup increments
42 # lockfile = lockfile to be kept during backup execution
43 # nicelevel = rsync command nice level
44 # enable_mv_timestamp_bug = set to "yes" if your system isnt handling timestamps correctly
46 # multiconnection = set to "yes" if you want to use multiconnection ssh support
49 # from = local or remote
50 # host = source hostname or ip, if remote backup
51 # port = remote port number (remote source only)
52 # user = remote user name (remote source only)
53 # testconnect = when "yes", test the connection for a remote source before backup
54 # include = include folder on backup
55 # exclude = exclude folder on backup
56 # ssh = ssh command line (remote source only)
57 # protocol = ssh or rsync (remote source only)
58 # rsync = rsync program
59 # rsync_options = rsync command options
60 # exclude_vserver = vserver-name (valid only if vservers = yes on backupninja.conf)
61 # numericids = when set to 1, use numeric ids instead of user/group mappings on rsync
62 # compress = if set to 1, compress data on rsync (remote source only)
63 # bandwidthlimit = set a badnwidth limit in kbps (remote source only)
64 # remote_rsync = remote rsync program (remote source only)
65 # id_file = ssh key file (remote source only)
66 # batch = set to "yes" to rsync use a batch file as source
67 # batchbase = folder where the batch file is located
68 # filelist = set yes if you want rsync to use a file list source
69 # filelistbase = folder where the file list is placed
72 # dest = backup destination type (local or remote)
73 # testconnect = when "yes", test the connection for a remote source before backup
74 # ssh = ssh command line (remote dest only)
75 # protocol = ssh or rsync (remote dest only)
76 # numericids = when set to 1, use numeric ids instead of user/group mappings on rsync
77 # compress = if set to 1, compress data on rsync (remote source only)
78 # host = destination host name (remote destination only)
79 # port = remote port number (remote destination only)
80 # user = remote user name (remote destination only)
81 # id_file = ssh key file (remote destination only)
82 # bandwidthlimit = set a badnwidth limit in kbps (remote destination only)
83 # remote_rsync = remote rsync program (remote dest only)
84 # batch = set to "yes" to rsync write a batch file from the changes
85 # batchbase = folder where the batch file should be written
86 # fakesuper = set to yes so rsync use the --fake-super flag (remote destination only)
89 # initscripts = absolute path where scripts are located
90 # service = script name to be stoped at the begining of the backup and started at its end
92 # You can also specify some system comands if you don't want the default system values:
97 # touch = touch command
101 # You dont need to manually specify vservers using "include = /vservers".
102 # They are automatically backuped if vserver is set to "yes" on you backupninja.conf.
107 # 20090329 - rhatto at riseup.net
109 # - Added support for:
110 # - Remote destinations
111 # - Long rotation format similar to maildir handler
112 # - Batch files through --read-batch and --write-batch
113 # - Custom file list using --files-from
114 # - SSH persistent connection using ControlMaster
115 # - The rsync:// protocol
116 # - Metadata folder for each backup folder
117 # - General refactoring
121 # function definitions
123 function eval_config {
137 getconf log /var/log/backup/rsync.log
147 getconf keepmonthly 1
150 getconf enable_mv_timestamp_bug no
152 getconf multiconnection no
159 getconf rsync_options "-av --delete --recursive"
161 if [ "$from" == "remote" ]; then
162 getconf testconnect no
167 if [ "$protocol" == "ssh" ]; then
168 # sshd default listen port
171 # rsyncd default listen port
176 getconf bandwidthlimit
177 getconf remote_rsync rsync
178 getconf id_file /root/.ssh/id_dsa
183 if [ "$batch" == "yes" ]; then
185 if [ ! -z "$batchbase" ]; then
194 getconf exclude_vserver
204 if [ "$dest" == "remote" ]; then
205 getconf testconnect no
210 if [ "$protocol" == "ssh" ]; then
211 # sshd default listen port
214 # rsyncd default listen port
219 getconf bandwidthlimit
220 getconf remote_rsync rsync
221 getconf id_file /root/.ssh/id_dsa
226 if [ "$batch" != "yes" ]; then
228 if [ "$batch" == "yes" ]; then
230 if [ ! -z "$batchbase" ]; then
242 getconf initscripts /etc/init.d
247 if [ "$dest" != "local" ] && [ "$from" == "remote" ]; then
248 fatal "When source is remote, destination should be local."
252 if [ "$from" != "local" ] && [ "$from" != "remote" ]; then
253 fatal "Invalid source $from"
257 backupdir="$mountpoint/$backupdir"
259 if [ "$dest" == "local" ] && [ ! -d "$backupdir" ]; then
260 error "Backupdir $backupdir does not exist"
264 if [ ! -z "$log" ]; then
265 mkdir -p `dirname $log`
268 if [ "$format" == "short" ]; then
269 if [ -z "$days" ]; then
272 keep="`echo $days - 1 | bc -l`"
276 if [ ! -z "$nicelevel" ]; then
277 nice="nice -n $nicelevel"
282 ssh_cmd="ssh -T -o PasswordAuthentication=no $host -p $port -l $user -i $id_file"
284 if [ "$from" == "remote" ] || [ "$dest" == "remote" ]; then
285 if [ "$testconnect" == "yes" ] && [ "$protocol" == "ssh" ]; then
286 test_connect $host $port $user $id_file
290 if [ "$multiconnection" == "yes" ]; then
291 ssh_cmd="$ssh_cmd -S $tmp/%r@%h:%p"
294 if [ $enable_mv_timestamp_bug == "yes" ]; then
298 for path in $exclude; do
299 excludes="$excludes --exclude=$path"
304 function rotate_short {
309 local metadata="`dirname $folder`/metadata"
311 if [[ "$keep" -lt 4 ]]; then
312 error "Rotate: minimum of 4 rotations"
316 if [ -d $folder.$keep ]; then
317 $nice $mv /$folder.$keep /$folder.tmp
320 for ((n=`echo "$keep - 1" | bc`; n >= 0; n--)); do
321 if [ -d $folder.$n ]; then
322 dest=`echo "$n + 1" | bc`
323 $nice $mv /$folder.$n /$folder.$dest
324 $touch /$folder.$dest
325 mkdir -p $metadata/`basename $folder`.$dest
326 date +%c%n%s > $metadata/`basename $folder`.$dest/rotated
330 if [ -d $folder.tmp ]; then
331 $nice $mv /$folder.tmp /$folder.0
334 if [ -d $folder.1 ]; then
335 $nice $cp -alf /$folder.1/. /$folder.0
340 function rotate_short_remote {
343 local metadata="`dirname $folder`/metadata"
346 if [[ "$2" -lt 4 ]]; then
347 error "Rotate: minimum of 4 rotations"
353 ##### BEGIN REMOTE SCRIPT #####
355 if [ -d $folder.$keep ]; then
356 $nice mv /$folder.$keep /$folder.tmp
359 for ((n=$(($keep - 1)); n >= 0; n--)); do
360 if [ -d $folder.\$n ]; then
362 $nice mv /$folder.\$n /$folder.\$dest
363 touch /$folder.\$dest
364 mkdir -p $metadata/`basename $folder`.\$dest
365 date +%c%n%s > $metadata/`basename $folder`.\$dest/rotated
369 if [ -d $folder.tmp ]; then
370 $nice mv /$folder.tmp /$folder.0
373 if [ -d $folder.1 ]; then
374 $nice $cp -alf /$folder.1/. /$folder.0
376 ##### END REMOTE SCRIPT #######
378 ) | (while read a; do passthru $a; done)
382 function rotate_long {
386 seconds_weekly=604800
387 seconds_monthly=2628000
389 keepweekly=$keepweekly
390 keepmonthly=$keepmonthly
395 if [ ! -d "$backuproot" ]; then
396 echo "Debug: skipping rotate of $backuproot as it doesn't exist."
400 for rottype in daily weekly monthly; do
401 seconds=$((seconds_${rottype}))
403 dir="$backuproot/$rottype"
404 metadata="$backuproot/metadata/$rottype.1"
406 if [ ! -d $dir.1 ]; then
407 echo "Debug: $dir.1 does not exist, skipping."
409 elif [ ! -f $metadata/created ] && [ ! -f $metadata/rotated ]; then
410 echo "Warning: metadata does not exist for $dir.1. This backup may be only partially completed. Skipping rotation."
414 # Rotate the current list of backups, if we can.
415 oldest=`find $backuproot -maxdepth 1 -type d -name $rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1`
416 [ "$oldest" == "" ] && oldest=0
417 for (( i=$oldest; i > 0; i-- )); do
418 if [ -d $dir.$i ]; then
419 if [ -f $metadata/created ]; then
420 created=`tail -1 $metadata/created`
421 elif [ -f $metadata/rotated ]; then
422 created=`tail -1 $metadata/rotated`
426 cutoff_time=$(( now - (seconds*(i-1)) ))
427 if [ ! $created -gt $cutoff_time ]; then
429 if [ ! -d $dir.$next ]; then
430 echo "Debug: $rottype.$i --> $rottype.$next"
431 $nice mv $dir.$i $dir.$next
432 mkdir -p $backuproot/metadata/$rottype.$next
433 date +%c%n%s > $backuproot/metadata/$rottype.$next/rotated
435 echo "Debug: skipping rotation of $dir.$i because $dir.$next already exists."
438 echo "Debug: skipping rotation of $dir.$i because it was created" $(( (now-created)/86400)) "days ago ("$(( (now-cutoff_time)/86400))" needed)."
445 if [ $keepweekly -gt 0 -a -d $backuproot/daily.$max -a ! -d $backuproot/weekly.1 ]; then
446 echo "Debug: daily.$max --> weekly.1"
447 $nice mv $backuproot/daily.$max $backuproot/weekly.1
448 mkdir -p $backuproot/metadata/weekly.1
449 date +%c%n%s > $backuproot/metadata/weekly.1/rotated
452 max=$((keepweekly+1))
453 if [ $keepmonthly -gt 0 -a -d $backuproot/weekly.$max -a ! -d $backuproot/monthly.1 ]; then
454 echo "Debug: weekly.$max --> monthly.1"
455 $nice mv $backuproot/weekly.$max $backuproot/monthly.1
456 mkdir -p $backuproot/metadata/monthly.1
457 date +%c%n%s > $backuproot/metadata/monthly.1/rotated
460 for rottype in daily weekly monthly; do
461 max=$((keep${rottype}+1))
462 dir="$backuproot/$rottype"
463 oldest=`find $backuproot -maxdepth 1 -type d -name $rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1`
464 [ "$oldest" == "" ] && oldest=0
465 # if we've rotated the last backup off the stack, remove it.
466 for (( i=$oldest; i >= $max; i-- )); do
467 if [ -d $dir.$i ]; then
468 if [ -d $backuproot/rotate.tmp ]; then
469 echo "Debug: removing rotate.tmp"
470 $nice rm -rf $backuproot/rotate.tmp
472 echo "Debug: moving $rottype.$i to rotate.tmp"
473 $nice mv $dir.$i $backuproot/rotate.tmp
480 function rotate_long_remote {
482 local backuproot="$1"
486 ##### BEGIN REMOTE SCRIPT #####
489 seconds_weekly=604800
490 seconds_monthly=2628000
492 keepweekly=$keepweekly
493 keepmonthly=$keepmonthly
496 if [ ! -d "$backuproot" ]; then
497 echo "Debug: skipping rotate of $backuproot as it doesn't exist."
501 for rottype in daily weekly monthly; do
502 seconds=\$((seconds_\${rottype}))
504 dir="$backuproot/\$rottype"
505 metadata="$backuproot/metadata/\$rottype.1"
507 if [ ! -d \$dir.1 ]; then
508 echo "Debug: \$dir.1 does not exist, skipping."
510 elif [ ! -f \$metadata/created ] && [ ! -f \$metadata/rotated ]; then
511 echo "Warning: metadata does not exist for \$dir.1. This backup may be only partially completed. Skipping rotation."
515 # Rotate the current list of backups, if we can.
516 oldest=\`find $backuproot -maxdepth 1 -type d -name \$rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1\`
517 [ "\$oldest" == "" ] && oldest=0
518 for (( i=\$oldest; i > 0; i-- )); do
519 if [ -d \$dir.\$i ]; then
520 if [ -f \$metadata/created ]; then
521 created=\`tail -1 \$metadata/created\`
522 elif [ -f \$metadata/rotated ]; then
523 created=\`tail -1 \$metadata/rotated\`
527 cutoff_time=\$(( now - (seconds*(i-1)) ))
528 if [ ! \$created -gt \$cutoff_time ]; then
530 if [ ! -d \$dir.\$next ]; then
531 echo "Debug: \$rottype.\$i --> \$rottype.\$next"
532 $nice mv \$dir.\$i \$dir.\$next
533 mkdir -p $backuproot/metadata/\$rottype.\$next
534 date +%c%n%s > $backuproot/metadata/\$rottype.\$next/rotated
536 echo "Debug: skipping rotation of \$dir.\$i because \$dir.\$next already exists."
539 echo "Debug: skipping rotation of \$dir.\$i because it was created" \$(( (now-created)/86400)) "days ago ("\$(( (now-cutoff_time)/86400))" needed)."
545 max=\$((keepdaily+1))
546 if [ \$keepweekly -gt 0 -a -d $backuproot/daily.\$max -a ! -d \$backuproot/weekly.1 ]; then
547 echo "Debug: daily.\$max --> weekly.1"
548 $nice mv $backuproot/daily.\$max $backuproot/weekly.1
549 mkdir -p $backuproot/metadata/weekly.1
550 date +%c%n%s > $backuproot/metadata/weekly.1/rotated
553 max=\$((keepweekly+1))
554 if [ \$keepmonthly -gt 0 -a -d $backuproot/weekly.\$max -a ! -d $backuproot/monthly.1 ]; then
555 echo "Debug: weekly.\$max --> monthly.1"
556 $nice mv $backuproot/weekly.\$max $backuproot/monthly.1
557 mkdir -p $backuproot/metadata/monthly.1
558 date +%c%n%s > $backuproot/metadata/monthly.1/rotated
561 for rottype in daily weekly monthly; do
562 max=\$((keep\${rottype}+1))
563 dir="$backuproot/\$rottype"
564 oldest=\`find $backuproot -maxdepth 1 -type d -name \$rottype'.*' | @SED@ 's/^.*\.//' | sort -n | tail -1\`
565 [ "\$oldest" == "" ] && oldest=0
566 # if we've rotated the last backup off the stack, remove it.
567 for (( i=\$oldest; i >= \$max; i-- )); do
568 if [ -d \$dir.\$i ]; then
569 if [ -d $backuproot/rotate.tmp ]; then
570 echo "Debug: removing rotate.tmp"
571 $nice rm -rf $backuproot/rotate.tmp
573 echo "Debug: moving \$rottype.\$i to rotate.tmp"
574 $nice mv \$dir.\$i $backuproot/rotate.tmp
578 ##### END REMOTE SCRIPT #######
580 ) | (while read a; do passthru $a; done)
584 function setup_long_dirs {
588 local dir="$destdir/$backuptype"
589 local tmpdir="$destdir/rotate.tmp"
590 local metadata="$destdir/metadata/$backuptype.1"
592 if [ ! -d $destdir ]; then
593 echo "Creating destination directory $destdir..."
597 if [ -d $dir.1 ]; then
598 if [ -f $metadata/created ]; then
599 echo "Warning: $dir.1 already exists. Overwriting contents."
601 echo "Warning: we seem to be resuming a partially written $dir.1"
604 if [ -d $tmpdir ]; then
607 echo "Fatal: could mv $destdir/rotate.tmp $dir.1 on host $host"
611 mkdir --parents $dir.1
613 echo "Fatal: could not create directory $dir.1 on host $host"
617 if [ -d $dir.2 ]; then
618 echo "Debug: update links $backuptype.2 --> $backuptype.1"
619 cp -alf $dir.2/. $dir.1
620 #if [ $? == 1 ]; then
621 # echo "Fatal: could not create hard links to $dir.1 on host $host"
626 [ -f $metadata/created ] && rm $metadata/created
627 [ -f $metadata/rotated ] && rm $metadata/rotated
631 function setup_long_dirs_remote {
635 local dir="$destdir/$backuptype"
636 local tmpdir="$destdir/rotate.tmp"
637 local metadata="$destdir/metadata/$backuptype.1"
641 ##### BEGIN REMOTE SCRIPT #####
642 if [ ! -d $destdir ]; then
643 echo "Creating destination directory $destdir on $host..."
647 if [ -d $dir.1 ]; then
648 if [ -f $metadata/created ]; then
649 echo "Warning: $dir.1 already exists. Overwriting contents."
651 echo "Warning: we seem to be resuming a partially written $dir.1"
654 if [ -d $tmpdir ]; then
656 if [ \$? == 1 ]; then
657 echo "Fatal: could mv $destdir/rotate.tmp $dir.1 on host $host"
661 mkdir --parents $dir.1
662 if [ \$? == 1 ]; then
663 echo "Fatal: could not create directory $dir.1 on host $host"
667 if [ -d $dir.2 ]; then
668 echo "Debug: update links $backuptype.2 --> $backuptype.1"
669 cp -alf $dir.2/. $dir.1
670 #if [ \$? == 1 ]; then
671 # echo "Fatal: could not create hard links to $dir.1 on host $host"
676 [ -f $metadata/created ] && rm $metadata/created
677 [ -f $metadata/rotated ] && rm $metadata/rotated
678 ##### END REMOTE SCRIPT #######
680 ) | (while read a; do passthru $a; done)
684 function move_files {
686 ref=$tmp/makesnapshot-mymv-$$;
694 function prepare_storage {
696 section="`basename $SECTION`"
698 if [ "$format" == "short" ]; then
701 info "Rotating $backupdir/$SECTION..."
702 echo "Rotating $backupdir/$SECTION..." >> $log
704 if [ "$dest" == "remote" ]; then
705 rotate_short_remote $backupdir/$SECTION/$section $keep
707 rotate_short $backupdir/$SECTION/$section $keep
708 if [ ! -d "$backupdir/$SECTION/$section.0" ]; then
709 mkdir -p $backupdir/$SECTION/$section.0
713 elif [ "$format" == "long" ]; then
715 if [ $keepdaily -gt 0 ]; then
717 elif [ $keepweekly -gt 0 ]; then
719 elif [ $keepmonthly -gt 0 ]; then
722 fatal "keeping no backups";
727 info "Rotating $backupdir/$SECTION/..."
728 echo "Rotating $backupdir/$SECTION/..." >> $log
730 if [ "$dest" == "remote" ]; then
731 rotate_long_remote $backupdir/$SECTION
732 setup_long_dirs_remote $backupdir/$SECTION $btype
734 rotate_long $backupdir/$SECTION
735 setup_long_dirs $backupdir/$SECTION $btype
738 elif [ "$format" == "mirror" ]; then
741 fatal "Invalid backup format $format"
749 if [ "$from" == "local" ]; then
751 elif [ "$from" == "remote" ]; then
752 if [ "$protocol" == "rsync" ]; then
753 orig="rsync://$user@$host:$port/$SECTION/"
755 orig="$user@$host:/$SECTION/"
763 if [ "$dest" == "local" ]; then
764 dest_path="$backupdir/$SECTION/$suffix/"
766 if [ "$protocol" == "rsync" ]; then
767 dest_path="rsync://$user@$host:$port/$backupdir/$SECTION/$suffix/"
769 dest_path="$user@$host:$backupdir/$SECTION/$suffix/"
775 function set_batch_mode {
777 local batch_file="$batchbase/$SECTION/$suffix"
779 if [ "$batch" == "read" ]; then
780 if [ -e "$batch_file" ]; then
783 batch_option="--read-batch=$batch_file"
785 fatal "Batch file not found: $batch_file"
788 elif [ "$batch" == "write" ]; then
789 mkdir -p `dirname $batch_file`
790 batch_option="--write-batch=$batch_file"
795 function update_metadata {
800 if [ "$dest" == "local" ]; then
801 metadata="`dirname $dest_path`/metadata/`basename $dest_path`"
803 date +%c%n%s > $metadata/created
804 $touch $backupdir/$SECTION/$suffix
806 folder="`echo $dest_path | cut -d : -f 2`"
807 metadata="`dirname $folder`/metadata/`basename $folder`"
811 ##### BEGIN REMOTE SCRIPT #####
813 date +%c%n%s > $metadata/created
814 ##### END REMOTE SCRIPT #######
816 ) | (while read a; do passthru $a; done)
822 function test_connect {
829 if [ -z "$host" ] || [ -z "$user" ]; then
830 fatal "Remote host or user not set"
834 debug "$ssh_cmd 'echo -n 1'"
835 result=`$ssh_cmd 'echo -n 1'`
837 if [ "$result" != "1" ]; then
838 fatal "Can't connect to $host as $user."
841 debug "Connected to $host successfully"
846 function set_lockfile {
848 if [ ! -z "$lockfile" ]; then
849 $touch $lockfile || warning "Could not create lockfile $lockfile"
854 function unset_lockfile {
856 if [ ! -z "$lockfile" ]; then
857 $rm $lockfile || warning "Could not remove lockfile $lockfile"
862 function set_filelist {
866 if [ "$filelist" == "yes" ]; then
867 if [ ! -z "$filelistbase" ]; then
868 if [ -e "$filelistbase/$SECTION/$suffix" ]; then
869 filelist_flag="--files-from=$filelistbase/$SECTION/$suffix"
871 warning "File list $filelistbase/$SECTION/$suffix not found."
874 warning "No filelistbase set."
880 function set_rsync_options {
882 if [ ! -z "$numericids" ]; then
883 rsync_options="$rsync_options --numeric-ids"
886 if [ "$from" == "local" ] || [ "$dest" == "local" ]; then
887 # rsync options for local sources or destinations
888 rsync_options="$rsync_options"
891 if [ "$from" == "remote" ] || [ "$dest" == "remote" ]; then
893 # rsync options for remote sources or destinations
895 if [ "$compress" == "1" ]; then
896 rsync_options="$rsync_options --compress"
899 if [ ! -z "$bandwidthlimit" ]; then
900 rsync_options="$rsync_options --bwlimit=$bandwidthlimit"
903 if [ "$fakesuper" == "yes" ]; then
904 remote_rsync="$remote_rsync --fake-super"
907 rsync_options=($rsync_options --rsync-path="$remote_rsync")
909 if [ "$protocol" == "ssh" ]; then
910 if [ ! -e "$id_file" ]; then
911 fatal "SSH Identity file $id_file not found"
914 debug RSYNC_RSH=\"$ssh_cmd\"
915 echo RSYNC_RSH=\"$ssh_cmd\" >> $log
926 function stop_services {
928 if [ ! -z "$service" ]; then
929 for daemon in $service; do
930 info "Stopping service $daemon..."
931 $initscripts/$daemon stop
937 function start_services {
941 if [ ! -z "$service" ]; then
942 for daemon in $service; do
943 info "Starting service $daemon..."
944 $initscripts/$daemon start
952 # mount backup destination folder as read-write
954 if [ "$dest" == "local" ]; then
955 if [ "$read_only" == "1" ] || [ "$read_only" == "yes" ]; then
956 if [ -d "$mountpoint" ]; then
957 mount -o remount,rw $mountpoint
959 error "Could not mount $mountpoint"
970 # remount backup destination as read-only
972 if [ "$dest" == "local" ]; then
973 if [ "$read_only" == "1" ] || [ "$read_only" == "yes" ]; then
974 mount -o remount,ro $mountpoint
982 # check partition for errors
984 if [ "$dest" == "local" ]; then
985 if [ "$fscheck" == "1" ] || [ "$fscheck" == "yes" ]; then
988 warning "Could not umount $mountpoint to run fsck"
990 $nice $fsck -v -y $partition >> $log
998 function include_vservers {
1000 # add vservers to included folders
1002 if [ "$vservers_are_available" == "yes" ]; then
1004 # sane permission on backup
1005 mkdir -p $backupdir/$VROOTDIR
1006 chmod 000 $backupdir/$VROOTDIR
1008 for candidate in $found_vservers; do
1009 candidate="`basename $candidate`"
1010 found_excluded_vserver="0"
1011 for excluded_vserver in $exclude_vserver; do
1012 if [ "$excluded_vserver" == "$candidate" ]; then
1013 found_excluded_vserver="1"
1017 if [ "$found_excluded_vserver" == "0" ]; then
1018 include="$include $VROOTDIR/$candidate"
1025 function start_mux {
1027 if [ "$multiconnection" == "yes" ]; then
1028 debug "Starting master ssh connection"
1029 $ssh_cmd -M sleep 1d &
1037 if [ "$multiconnection" == "yes" ]; then
1038 debug "Stopping master ssh connection"
1039 $ssh_cmd pkill sleep
1044 # the backup procedure
1053 echo "Starting backup at `date`" >> $log
1055 for SECTION in $include; do
1063 info "Syncing $SECTION on $dest_path..."
1064 debug $nice $rsync "${rsync_options[@]}" $filelist_flag $excludes $batch_option $orig $dest_path
1065 $nice $rsync "${rsync_options[@]}" $filelist_flag $excludes $batch_option $orig $dest_path >> $log
1067 if [ "$?" != "0" ]; then
1068 warning "Rsync error when trying to transfer $SECTION"
1081 echo "Finnishing backup at `date`" >> $log