3 ### Check that dumps have been made as expected.
5 ### (c) 2013 Mark Wooding
8 ###----- Licensing notice ---------------------------------------------------
10 ### This file is part of the `rsync-backup' program.
12 ### rsync-backup is free software; you can redistribute it and/or modify
13 ### it under the terms of the GNU General Public License as published by
14 ### the Free Software Foundation; either version 2 of the License, or
15 ### (at your option) any later version.
17 ### rsync-backup is distributed in the hope that it will be useful,
18 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ### GNU General Public License for more details.
22 ### You should have received a copy of the GNU General Public License
23 ### along with rsync-backup; if not, write to the Free Software Foundation,
24 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 ###--------------------------------------------------------------------------
32 ### Stubs for the configuration file.
43 ###--------------------------------------------------------------------------
44 ### Output format switch.
47 defformat () { formats=$formats$1:; }
55 case $fmtstate in $state) break ;; esac
56 case "$fmtstate,$state" in
62 fmtstate=hosttbl_begin
64 hosttbl_begin,hosttbl_*)
65 ${fmt}_hosttbl_begin "$@"
68 hosttbl_host,hosttbl_fs)
71 hosttbl_fs,hosttbl_host)
72 ${fmt}_hosttbl_sep "$@"
75 hosttbl_begin,* | hosttbl_end,*)
76 fmtstate=logdump_begin
79 ${fmt}_hosttbl_end "$@"
82 logdump_begin,logdump_*)
85 logdump_out,logdump_info | logdump_out,logdump_file)
88 logdump_*,logdump_begin)
89 ${fmt}_logdump_end "$@"
90 fmtstate=logdump_begin
105 echo >&2 "$quis: FATAL! NO PROGRESS IN FMT STATE MACHINE"
111 ${fmt}_$fmtstate "$@"
114 ###--------------------------------------------------------------------------
115 ### Plain text output.
120 txt_hosttbl_begin () { :; }
121 txt_hosttbl_host () { echo "HOST $1"; }
122 txt_hosttbl_fs () { printf " %-23s %s\n" "$2" "$4"; }
123 txt_hosttbl_sep () { echo; }
124 txt_hosttbl_end () { :; }
126 txt_logdump_begin () {
129 -----------------------------------------------------------------------------
135 txt_logdump_info () { echo "!!! $3"; }
136 txt_logdump_file () { cat "$3"; }
137 txt_logdump_end () { :; }
144 ###--------------------------------------------------------------------------
151 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
152 "http://www.w3c.org/TR/html4/strict.dtd">
155 <title>$now rsync-backup report</title>
156 <style type='text/css'><!--
163 h1, h2 { font-family: sans-serif; font-weight: bold; }
167 border-bottom: solid medium black;
173 border-top: solid thin black;
185 border-top: solid medium black;
195 border-collapse: collapse;
196 display: inline-table;
199 table.hosttbl tr.fs td {
200 border: solid thin black;
202 table.hosttbl td { padding: 0.5ex 0.5em; }
203 table.hosttbl tr.host td {
207 font-family: monospace;
209 table.hosttbl td.fs {
210 font-family: monospace;
213 table.hosttbl td.winning { background: #2f4; }
214 table.hosttbl td.failed { background: #f80; }
215 table.hosttbl td.broken { background: #f11; }
216 table.hosttbl td.never { background: #66f; }
223 border: solid thin black;
227 .hide { display: none; }
231 font-weight: initial;
239 border: solid thin black;
242 <script type='text/javascript'><!--
243 var LAST_EXPAND = null;
244 function elt(id) { return document.getElementById(id); }
245 function add_elt_class(elt, cls) {
246 if (!elt.className.match('\\\\b' + cls + '\\\\b'))
247 elt.className += ' ' + cls;
249 function rm_elt_class(elt, cls) {
250 elt.className = elt.className.replace(
251 new RegExp('\\\\s*\\\\b' + cls + '\\\\b\\\\s*'), ' ');
253 function toggle_expand(ev, tag) {
254 var d = elt('logdump-' + tag);
255 var b = elt('expand-' + tag);
256 if (d.className.match(/\bhide\b/)) do_show(d, b);
260 function do_show(d, b) {
261 rm_elt_class(d, 'hide');
262 b.textContent = '[hide]';
264 function do_hide(d, b) {
265 add_elt_class(d, 'hide');
266 b.textContent = '[show]';
267 if (LAST_EXPAND !== null && d === LAST_EXPAND[0])
270 function expand_log(tag) {
271 if (LAST_EXPAND !== null) do_hide(LAST_EXPAND[0], LAST_EXPAND[1]);
272 var d = elt('logdump-' + tag);
273 var b = elt('expand-' + tag);
274 LAST_EXPAND = [d, b];
277 function make_toggle_button(tag) {
279 "<a class=expand-button id='expand-" + tag + "' href='#' " +
280 "onclick='toggle_expand(event, \"" + tag + "\")'>" +
284 function hide_logdump(tag) {
285 add_elt_class(elt('logdump-' + tag), 'hide');
291 <h1><tt>rsync-backup</tt> report: $now_dow $now</tt></h1>
295 html_hosttbl_begin () {
302 html_hosttbl_host () {
304 <table class=hosttbl>
305 <tr class=host><td colspan=2>$1</tc>
311 winning) link="" knil="" ;;
313 link="<a href='#log-$host:$fs' onclick='expand_log(\"$host:$fs\")'>"
320 <td class=$3>$link$4$knil</td>
324 html_hosttbl_sep () {
330 html_hosttbl_end () {
336 html_logdump_begin () {
339 <h2 id='log-$1:$2'><a name='log-$1:$2'>Log tail for <tt>$1:$2</tt></a>
340 <script type='text/javascript'><!--
341 make_toggle_button('$1:$2');
346 html_logdump_info () {
348 <div id='logdump-$1:$2' class=logdump-info><script type='text/javascript'><!--
349 hide_logdump('$1:$2');
354 html_logdump_file () {
356 <pre id='logdump-$1:$2' class=logdump>
357 <script type='text/javascript'><!--
358 hide_logdump('$1:$2');
367 html_logdump_end () { :; }
373 Checked at $now $now_time.
374 <br><tt>rsync-backup</tt> $VERSION; © 2014 Mark Wooding
384 ###--------------------------------------------------------------------------
387 INDEXDB=@pkglocalstatedir@/index.db
397 case $fs in *:*) fs=${fs%%:*} ;; esac
399 for p in "${patterns[@]}"; do
400 case $host:$fs in $p) matchp=t; break ;; esac
402 case $matchp in nil) return ;; esac
403 when=$(sqlite3 $INDEXDB \
404 "SELECT MAX(date) FROM idx WHERE host = '$host' AND fs = '$fs';")
419 jdn=$(julian "$when")
420 ago=$(( $now_jdn - $jdn ))
421 case $ago in 1 | -1) days=day ;; *) days=days ;; esac
423 -*) class=future; info="${ago#-} $days in the FUTURE" ;;
424 1 | 2) class=failed; info="$ago $days ago" ;;
425 *) class=broken; info="$ago $days ago" ;;
436 fmt hosttbl_host $host
440 fmt hosttbl_fs $host $fs $class "$info"
442 nil) failures="$failures $host:$fs" ;;
450 for fail in $failures; do
451 host=${fail%:*} fs=${fail##*:}
453 for i in "$logdir/$host/$fs.$now#"*; do
454 if [ -f "$i" ]; then log=$i; any=t; fi
456 fmt logdump_begin $host $fs
458 t) fmt logdump_file $host $fs "$log" ;;
459 nil) fmt logdump_info $host $fs "No log! No backup attempted." ;;
464 ###--------------------------------------------------------------------------
465 ### Read the configuration and we're done.
468 echo "usage: $quis [-v] [-c CONF] [-f FORMAT] [PATTERNS...]"
472 echo "$quis, rsync-backup version $VERSION"
477 while getopts "hVc:f:v" opt; do
480 V) version; config; exit 0 ;;
485 *) echo >&2 "$0: unknown format \`$OPTARG'"; exit 1 ;;
493 shift $((OPTIND - 1))
495 0) declare -a patterns=("*") ;;
496 *) declare -a patterns=("$@") ;;
499 now=$(date +"%Y-%m-%d")
500 now_time=$(date +"%H:%M:%S %z")
501 now_dow=$(date +"%A")
502 now_jdn=$(julian $now)
507 ###----- That's all, folks --------------------------------------------------