chiark / gitweb /
chiark-backup's snaprsync has new rsynccompress option.
[chiark-utils.git] / backup / snaprsync
1 #!/bin/bash
2 #
3 # usage: snaprsync <setting>... <positionals>
4 #  <setting> is --<name>=<value>
5 #  <positionals> are assigned to unused mandatory values in order
6 # mandatory:
7 #   rhost device mountpoint localarea 
8 # optional:
9         localprevious=
10         snapkind=lvm
11         rsharedir=/usr/share/chiark-backup 
12         retcdir=/etc/chiark-backup
13         rvardir=/var/lib/chiark-backup
14         bwlimit=
15         subdir=.
16         rsyncopts=
17         rsynccompress=z
18         sshopts=
19         summer=summer
20
21 set -e
22
23 badusage () { echo >&2 "snaprsync: bad usage: $1"; exit 12; }
24 nb_echo () { (echo "$@"); } # See Debian #382798
25 x () { nb_echo "+ $@"; "$@"; }
26 xspawned () { eval "${1}pid=$!; nb_echo \"+[$!] ($1) &\";"; }
27 xwait () { eval "nb_echo \"+[\$${1}pid] ($1)...\"; wait \$${1}pid;"; }
28
29 while true; do
30         case "$1" in
31         --?*=*)
32                 name=${1#--}; name=${name%%=*}
33                 value=${1#--*=}
34                 case "$name" in
35                 rhost|device|mountpoint|localarea);;
36                 localprevious|snapkind|rsharedir|retcdir|rvardir|bwlimit);;
37                 subdir|rsyncopts|rsynccompress|sshopts|summer);;
38                 *) badusage "unknown setting $name";;
39                 esac
40                 eval "$name=\$value"
41                 ;;
42         --)     shift; break ;;
43         -*)     badusage "unknown option $1" ;;
44         *)      break ;;
45         esac
46         shift
47 done
48
49 for name in rhost device mountpoint localarea; do
50         eval "value=\$$name"
51         if [ "x$value" != x ]; then continue; fi
52         if [ $# = 0 ]; then badusage "no value for setting $name"; fi
53         eval "$name=$1"
54         shift
55 done
56
57 datefmt='%Y-%m-%d %H:%M:%S Z'
58 rsync="rsync ${bwlimit:+--bwlimit} $bwlimit"
59 export RSYNC_RSH="ssh -o compression=no $sshopts"
60 sshpfx='PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin; export PATH; '
61
62 ssh $sshopts $rhost "$sshpfx date -u '+$rhost $datefmt start'"
63 ssh $sshopts $rhost "$sshpfx id"
64 ssh $sshopts $rhost "$sshpfx ls -d $rsharedir"
65 ssh $sshopts $rhost "$sshpfx ls -d $rvardir"
66
67 test -d $localarea || x mkdir $localarea
68 ournode=`uname -n`
69 rsumsfile=for-$ournode.sums
70 summer="$summer -ACDbtqfx"
71
72 td=/dev/enoent
73 rc=12
74 trap 'rm -rf $td; exit $rc' 0
75 td=`mktemp -td`
76
77 mkfifo -m 600 $td/sentinel
78 exec 4<>$td/sentinel
79
80 x ssh $sshopts $rhost "$sshpfx $rsharedir/snap-drop $rvardir"
81 ssh $sshopts $rhost "
82         $sshpfx
83         set -e
84         cd $rvardir
85         echo '$retcdir/snap/$snapkind drop $rvardir' >snap-drop.new
86         mv snap-drop.new snap-drop
87 "
88 x ssh $sshopts $rhost "$sshpfx $retcdir/snap/$snapkind snap $rvardir $device $mountpoint"
89 ssh $sshopts $rhost <$td/sentinel 4<&- "
90   $sshpfx
91   set -e
92   date -u '+$rhost $datefmt main'
93   exec 3<&0 0</dev/null
94   (set +e; read x <&3; kill 0) &
95   cd $rvardir
96   umask 077
97   exec 3>$rsumsfile
98   cd snap-mount
99   $summer . >&3
100   date -u '+$rhost $datefmt sumsdone'
101   cd ..
102 " &
103 xspawned rsum
104 x $rsync -aHSx$rsynccompress --numeric-ids --delete $rsyncopts \
105         ${localprevious:+--link-dest} $localprevious \
106         $rhost:$rvardir/snap-mount/$subdir $localarea/.
107 date -u "+ $datefmt rsyncdone"
108
109 exec 3>$localarea,lsums
110 (cd $localarea && \
111  $summer . >&3) &
112 xspawned lsum
113 exec 3>&-
114
115 xwait rsum
116 exec 4<&-
117 date -u "+ $datefmt sumsdone"
118 x ssh $sshopts $rhost "$sshpfx $rsharedir/snap-drop"
119
120 if [ "x${localprevious}" != x ] && test -f "$localprevious,rsums"; then
121         cp "$localprevious,rsums" "$localarea,rsums"
122 fi
123 x $rsync -p \
124         $rhost:$rvardir/$rsumsfile \
125         "$localarea,rsums"
126
127 xwait $lsum
128 date -u "+ $datefmt checking"
129
130 set +e
131 diff -u <(sed -e 's/^mountpoint/dir       /' "$localarea,rsums") \
132   "$localarea,lsums" >"$localarea,sumsdiff"
133 diffrc=$?
134 set -e
135 test $diffrc = 0 || test $diffrc = 1
136
137 date -u "+ $datefmt checked $diffrc"
138 rc=$diffrc