#!/bin/bash # $Header: /CVSROOT/public/scylla-charybdis/md5backup/bin/compare.sh,v 1.4 2006/10/03 21:16:33 tino Exp $ # # Simple compare script. # # THIS CAN BE SEEN AS A BASE FOR A RESTORE SCRIPT! # Note that there will never be restore program. # You always will be able to restore using the shell only. # # Read the log in reverse and compare all the files found # and report the differences. # # $Log: compare.sh,v $ # Revision 1.4 2006/10/03 21:16:33 tino # See Changelog, commit for dist # # Revision 1.3 2005/10/10 23:19:13 tino # typo corrected (md5check -> md5sum) # # Revision 1.2 2005/03/05 23:28:39 tino # support for multi file store added # # Revision 1.1 2004/10/05 02:02:48 tino # added # # Change "compare" to "restore" to have a protoype restore method # But see below, there is a second safety belt below (hunt for # restore). If you don't know how, better don't try ;) MODE=compare host="`hostname -f`" [ -z "$host" ] && host="`hostname`" [ -z "$host" ] && host="`cat /etc/hostname`" [ -z "$host" ] && host="HOSTNAME" if [ 0 = $# ] then echo "Usage: `basename "$0"` /backup/md5backup/log/$host [outpath] [grep] Compare files in the file store with their originals and report differences to stderr. The path can be '' for default. If you get a lot of errors, try running this as root. Usually you don't need this, you can also do: md5sum --check /backup/md5backup/md5/$host cd /backup/md5backup && bin/check.sh" >&2 exit 1 fi SRC="$1" [ -z "$SRC" ] && SRC="/backup/md5backup/log/$host" DIR="`dirname "$SRC"`" DIR="`dirname "$DIR"`/out" OUT="${2:-$DIR}" GREP="$3" if [ ! -d "$OUT" ] then echo "Required paths not found: $OUT Give correct file store path as second argument" exit 1 fi # SET DUMMY TO NOTHING TO RESTORE (I need it to be able to test!) DUMMY=echo restore() { if [ ! -f "$1" ] then echo "missing $1 ($2)" >&2 inc miss return fi [ -f "$2" ] && inc diff inc clean if ! $DUMMY cp --backup=t "$@" then inc del $DUMMY mkdir -p "`dirname "$2"`" && $DUMMY cp --backup=t "$@" fi && echo "restored $2" >&2 || echo "failed $2" >&2 } CLR="`tput el`" tac "$SRC" | # old: YYYY-MM-DD HH:MM:SS md5 MD5SUM nr PATH # new: YYYY-MM-DD HH:MM:SS md5 nnnKB MD5SUM nr PATH # new: YYYY-MM-DD HH:MM:SS known md5 MD5SUM nr PATH # In V0.4.x this format will change again. awk -v GREP="$GREP" ' $3=="md5" || $3=="known" { sub(/^[^ ]* [^ ]* [^ ]* /,""); if (length($1)!=32) sub(/^[^ ]* /,""); md5=$1 nr=$2 sub(/^[^ ]* [^ ]* /,""); if (had[$0]++) next if (GREP=="" || $0 ~ GREP) print substr(md5,1,2) "/" substr(md5,3,2) "/" md5 "." nr ".md5 " $0 }' | { warn=false nr=0 diff=0 del=0 miss=0 clean=0 max=69 inc() { eval test -z \"\${$1//9/}\" && let max-- let $1++ } compare() { if [ ! -f "$2" ] then if [ -f "$1" ] then echo -n "$CLR" echo "deleted $2" >&2 inc del else # yes, reported to stdout echo "clean $2$CLR" inc clean fi elif [ ! -f "$1" ] then echo "missing $1$CLR" echo "Advice! Make a full backup! Remove dbm/`basename "$SRC"`" warn=: echo "missing $1" >&2 inc miss else echo -n "$CLR" echo "diff $2" >&2 inc diff fi } while read -r md5 file do inc nr if [ -n "${file:max}" ] then echo -n "$nr-$clean+$diff*$del?$miss ${file:0-max:max} " else echo -n "$nr-$clean+$diff*$del?$miss $file$CLR " fi for dir in "$OUT" "$OUT"[0-9] do src="$dir/$md5" [ -f "$src" ] && break done cmp -s "$src" "$file" || $MODE "$src" "$file" done if $warn then echo "Serious inconsistencies detected! Hunt for 'missing' files" echo "It looks like you need a full backup. For this do:" echo "Remove database dbm/`basename "$SRC"`" echo "Then run md5backup again." echo "Serious inconsistencies detected! Hunt for 'missing' files" >&2 fi }