#!/bin/csh -f # This shell script checks whether all dumps are up to date on all # machines in this machine's domain. # A sample .cbackupsrc (which controls output) is at the end of this # file. It is dependent on my "jd" script, so it will need a little # reconfiguring by you... # Future plans: # discover "conflicts" including # filesystems dumped which are ignored # filesystems dumped in more than one dump # (These await Adrian's gathering of the dump scripts) switch (`uname -s``uname -r`) case SunOS4*: set BASENAME = /bin/basename set DF = /bin/df set FSTAB = /etc/fstab set HOSTNAME = /bin/hostname set MTAB = /etc/mtab set MOUNT = /etc/mount set NAWK = /usr/bin/nawk set DEVPOS = 2 # see below set DEVMIN = 1 set PING = /usr/etc/ping breaksw case SunOS5*: set BASENAME = /usr/ucb/basename set DF = /usr/ucb/df set FSTAB = /etc/vfstab set HOSTNAME = /usr/ucb/hostname set MTAB = /etc/mnttab set MOUNT = "/etc/mount -p" set NAWK = /usr/bin/nawk set DEVPOS = 2 # see below set DEVMIN = 1 set PING = /usr/sbin/ping breaksw case OSF1*: set BASENAME = /usr/ucb/basename set DF = /bin/df set FSTAB = /etc/fstab set HOSTNAME = /bin/hostname set MOUNT = "/usr/sbin/mount" set NAWK = /usr/bin/nawk set DEVPOS = 2 # see below set DEVMIN = 1 set PING = /usr/sbin/ping breaksw case Linux2*: set BASENAME = /bin/basename set DF = /bin/df set FSTAB = /etc/fstab set HOSTNAME = /bin/hostname set MOUNT = "/bin/mount" set NAWK = /bin/gawk set DEVPOS = 1 # see below set DEVMIN = 0 set PING = /bin/ping breaksw default: echo cbackups does not run under `uname -s` `uname -r` yet exit breaksw endsw set path = ( /usr/local/bin $path ) set BASE = `$BASENAME $0` set WATROUS = ~watrous if (-e /usr/local/bin/timeout) then # set RSH = "/usr/local/bin/timeout 600 rsh" set RSH = "/usr/local/bin/timeout 600 ssh" else # set RSH = rsh set RSH = ssh endif while ($#argv) switch ("$1") case "-d": set DOMAIN; shift breaksw case "-f": set RCFSW = "-f $2" set RCFILE = $2; shift ; shift breaksw case "-n": set NETGROUP = $2; shift ; shift breaksw case "-lv": set LVERBOSE; shift breaksw case "-rv": set RVERBOSE = "-v"; shift breaksw case "-D": set DEBUG # breaksw # fall through case "-v": set LVERBOSE; set RVERBOSE = "-v"; shift breaksw case -p*: # ping should timeout in this number of seconds if ("$1" == "-p") then set PTIME = $2 shift;shift else set PTIME = `echo "$1" | sed 's;^-p;;'` shift endif breaksw default: exec echo ${0}: what does \"$1\" mean\? endsw end set FHOST = `$HOSTNAME` #set SHOST = `$HOSTNAME | sed 's;\..*;;'` set SHOST = `hostname | sed 's;\.[Rr][Uu][Tt][Gg][Ee][Rr][Ss]\.[Ee][Dd][Uu];;'` set DIR = `dirname $0` if ("$DIR" == ".") then set DIR = `pwd` endif # determine whether more space is on /tmp or /var/tmp set TS = `$DF /tmp | grep /` set VTS = `$DF /var/tmp | grep /` if ($TS[4] > $VTS[4]) then set TMP = /tmp/${BASE}$$ else set TMP = /var/tmp/${BASE}$$ endif if (! $?RCFILE) then if (-e ~/.${BASE}rc) then set RCFILE = ~/.${BASE}rc else if (-e $DIR/.${BASE}rc) then set RCFILE = $DIR/.${BASE}rc endif endif if (! $?RCFILE) then set RCFILE else if (! -e $RCFILE) then echo $RCFILE does not exist on $FHOST set RCFILE set RCFSW endif endif if (! $?RCFSW) set RCFSW # I'm sure I had a good reason for doing this at one point, but I don't # recall it right now and it breaks RCFILE for rinehart on henson. I'll # remove it and see if I miss it and recall what I *wanted* to do. daw, 8/8/97 #if (($?DOMAIN && $?RVERBOSE) || (! $?DOMAIN && $?LVERBOSE)) set RCFILE if ("$RCFILE" != "") then set RCBASE = `$BASENAME $RCFILE` else set RCBASE endif if (! $?DOMAIN) goto local if (! $?RVERBOSE) set RVERBOSE echo " *** $BASE on $SHOST begun at `date` ***" # First, determine all the ypservers in this domain. set DOMAIN = `domainname` cp /dev/null $TMP.all if ("$DOMAIN" == "") goto noyp if (! $?NETGROUP) then if ($?LVERBOSE) echo `date` - collecting ypserver information... foreach HOST ( `ypcat -k ypservers | sed 's; .*;;'` ) if ($?LVERBOSE) echo server: $HOST if ($HOST == $FHOST || $HOST == $SHOST) then if (-r /etc/ypclients) then ( cat /etc/ypclients >> $TMP.all ) >& $TMP.err else ( /usr/local/bin/slide cat /etc/ypclients >> $TMP.all ) >& $TMP.err endif else ( $RSH $HOST cat /etc/ypclients >> $TMP.all ) >& $TMP.err endif # If no ypclients, try securenets egrep "No such file|cannot open" $TMP.err > /dev/null # egrep "No such file|cannot open" $TMP.err if (! $status) then if ($?DEBUG) echo Trying securenets if ($HOST == $FHOST || $HOST == $SHOST) then set SN = `/usr/local/bin/slide grep . /var/yp/securenets |& grep -v "#"` else # set SN = `$RSH $HOST /usr/local/bin/slide grep . /var/yp/securenets | grep -v "#"` # $RSH $HOST /usr/local/bin/slide grep . /var/yp/securenets |& grep -v "#" > $TMP.err # set SN = `cat $TMP.err` $RSH $HOST echo xYzZy \; \ /usr/local/bin/slide grep . /var/yp/securenets |& grep -v "#" > $TMP.err @ N = `grep -n xYzZy $TMP.err | sed 's;:.*;;'` + 1 set SN = `tail +$N $TMP.err` endif # egrep "No such file|cannot open" $TMP.err > /dev/null echo "$SN" | egrep "No such file|cannot open|can.t open" > /dev/null if ($status) then while ($#SN) if ($?DEBUG) echo $SN[1] $SN[2] switch ($SN[1]) case host: if ($SN[2] == "127.0.0.1") then hostname >> $TMP.all else # handle output from both flavors of host program: /usr/local/bin/host $SN[2] | & \ egrep "domain name pointer|^Name: " | \ sed -e 's;.*pointer ;;' -e 's;^Name: ;;' | \ grep . >> $TMP.all if ($status) echo Unknown host in $HOST\'s securenets: $SN[2] endif breaksw case 255.255.255.0: set SNSIZE = 255 goto common case 255.255.255.128: set SNSIZE = 127 common: set Q = `echo $SN[2] | sed 's;\.; ;g'` @ HN = $Q[4] + 1 # @ HNMAX = $Q[4] + 255 @ HNMAX = $Q[4] + $SNSIZE while($HN <= $HNMAX) # handle output from both flavors of host program: /usr/local/bin/host $Q[1].$Q[2].$Q[3].$HN | & \ egrep "domain name pointer|^Name: " | \ sed -e 's;.*pointer ;;' -e 's;^Name: ;;' | \ grep . >> $TMP.all @ HN ++ end breaksw default: echo Unknown line in $HOST\'s securenets: $SN[1] $SN[2] endsw shift SN; shift SN end else # echo no ypclients or securenets on `hostname` # echo no ypclients or securenets on $HOST echo problem accessing securenets on ${HOST}: $SN set THOST = `echo $HOST | sed 's;\..*;;'` echo "" echo " cbackups couldn't access either /etc/ypclients or /var/yp/securenets" echo " on $THOST. One of these files should exist or $THOST will" echo " give anybody on the internet data for the $DOMAIN domain." echo "" endif else if ( ! -z $TMP.err && $?LVERBOSE ) then echo -n "error contacting ${HOST}: " cat $TMP.err endif end else Sys/netgroup $NETGROUP | sed -e 's;(;;' -e 's;,.*;;' > $TMP.all endif noyp: if (-z $TMP.all) then hostname > $TMP.all endif #egrep -v '^#|^wp1|-fddi$' $TMP.all | tr A-Z a-z | sed 's;\.rutgers\.edu$;;' | sort -u > $TMP.unique cat $TMP.all | tr "[A-Z]" "[a-z]" | sed 's;\.rutgers\.edu$;;' | egrep -v '^#|^caboose|^track-master|^wp1|-fddi$' | sort -u > $TMP.unique if ($?LVERBOSE) then if ("$DOMAIN" != "") then set DOMAINMSG = "s in $DOMAIN" else set DOMAINMSG = " "`cat $TMP.unique` endif if (! $?NETGROUP) then echo `date` - checking backups for host$DOMAINMSG else echo `date` - checking backups for host$DOMAINMSG, netgroup $NETGROUP endif endif set HOSTS if (! $?PTIME) set PTIME foreach HOST ( `cat $TMP.unique` ) if ($?LVERBOSE) echo host: $HOST if ("$RCFILE" != "") then if (-r $RCFILE) then set TARG = "^ignore $HOST"\$ grep "$TARG" $RCFILE > /dev/null if (! $status) then if ($?LVERBOSE) echo "${HOST} being ignored" continue endif endif endif $PING $HOST $PTIME > /dev/null if ($status) then if ($?LVERBOSE) echo "${HOST} does not respond to ping" continue endif if ($HOST == $FHOST || $HOST == $SHOST) then ( domainname > $TMP.out ) >& $TMP.err set STATUS = $status else ( $RSH $HOST domainname > $TMP.out ) >& $TMP.err set STATUS = $status endif if ($STATUS && ! -z $TMP.err) then if ($?LVERBOSE) then echo -n "error contacting ${HOST}: " cat $TMP.err endif continue else if ($STATUS) then if ($?LVERBOSE) then if ($STATUS == "60") then echo "error contacting ${HOST}: timed out" else echo "error contacting ${HOST}: status = $STATUS" endif endif continue endif set HOSTDOMAIN = `cat $TMP.out` if ("$HOSTDOMAIN" != "$DOMAIN") then if ($?LVERBOSE) echo "${HOST} is in $HOSTDOMAIN, not $DOMAIN" continue endif # echo " debug: adding in $HOST" set HOSTS = ( $HOSTS $HOST ) echo " $HOST" if ($HOST == $FHOST || $HOST == $SHOST) then if ($?DEBUG) echo $DIR/$BASE $RVERBOSE $RCFSW ( $DIR/$BASE $RVERBOSE $RCFSW > $TMP.out ) >& $TMP.err set STATUS = $status else # echo $RSH $HOST -n $DIR/$BASE $RVERBOSE $RCFSW if ($?DEBUG) echo $RSH $HOST -n $DIR/$BASE $RVERBOSE $RCFSW ( $RSH $HOST -n $DIR/$BASE $RVERBOSE $RCFSW > $TMP.out ) >& $TMP.err set STATUS = $status endif if ($STATUS && ! -z $TMP.err) then echo -n "error recontacting ${HOST}: " cat $TMP.err continue else if ($STATUS) then if ($STATUS == "60") then echo "error recontacting ${HOST}: timed out" else echo "error recontacting ${HOST}: status = $STATUS" endif continue endif cat $TMP.out end echo " *** $BASE on $SHOST finished at `date` ***" if ($?LVERBOSE) echo `date` - done goto done local: grep -s "^/dev/" $FSTAB > /dev/null if ($status) exit # no dumps needed if (! -e /etc/dumpdates ) exec echo Dumps have never been done on `$HOSTNAME` set DFLINE = `$DF /tmp |& grep /` if ($#DFLINE != 6) then echo ${BASE}: cannot determine available space on /tmp - `$HOSTNAME` echo $DFLINE else if ($DFLINE[4] == 0) then exec echo ${BASE}: no available space on /tmp - `$HOSTNAME` endif cat > $TMP.nawk << EOF BEGIN { debug=0 jd = "$WATROUS/Sys/jd -y " hcmd = "$HOSTNAME | sed 's;.rutgers.edu;;'" hcmd | getline host close(hcmd) # jd = "/usr/local/bin/ctime -t " jd | getline now close(jd) zcmd = "date | awk '{print \$5}'" zcmd | getline zone close(zcmd) # print zone type[0] = "full" type[1] = "incremental" number["full"] = 0 number["incremental"] = 1 cmd = "$MOUNT ; echo EOF" while (inp != "EOF") { cmd|getline inp if (inp != "EOF") { split(inp,tempa) if (tempa[5] == "4.2" || tempa[4] == "ufs" || tempa[5] == "ufs" || tempa[5] == "ext2" || tempa[5] == "ext3") { if (! (index(tempa[1],"/dev/sr") || index(tempa[1],"/vol/dev/"))) { if(debug) print "From ${MOUNT}:", tempa[3], "is", tempa[1] devname[tempa[1]] = tempa[3] namedev[tempa[3]] = tempa[1] } } } } } { if (FILENAME != ofile) { x = split(FILENAME,tempa,"/") file = tempa[x] ofile = FILENAME } if (file == "dumpdates") { if (substr(\$0,1,1) != "/") next # if (split(\$1,tempa,"/") != 3) print "Odd device: " \$1 n = split(\$1,tempa,"/") if(debug) print "From dumpdates:",\$1 if (n == 3) { dev = "/" tempa[2] "/" substr(tempa[3],$DEVPOS,length(tempa[3])-$DEVMIN) } else if (n == 4 && tempa[3] == "rdsk") { dev = "/" tempa[2] "/" substr(tempa[3],2,length(tempa[3])-1) "/" tempa[4] } else if (n == 5 && tempa[4] == "rdsk") { dev = "/" tempa[2] "/" tempa[3] "/" substr(tempa[4],2,length(tempa[4])-1) "/" tempa[5] } else print "Odd device: " \$1 if(debug) print "dev =",dev dump[\$2 ":" dev] = \$3 " " \$4 " " \$5 " " \$6 " " \$7 } else if (file == "$RCBASE") { if(NF == 0) next if (substr(\$1,1,1) == "#") next if (\$1 == "ignore") { if (host == \$2) { if (NF == 2) IGNORE = 1 else if (NF == 3) ignore[\$3] = 1 else ignore[number[\$4] ":" namedev[\$3]] = 1 } else if (substr(\$2,1,1) == "/") { if (NF == 2) ignore[\$2] = 1 else { ignore[0 ":" namedev[\$3]] = 1 ignore[1 ":" namedev[\$3]] = 1 } } } else if (\$1 == "max") { # max[\$2] = \$3 * 86400 max[\$2] = \$3 } else if (\$1 == "maximum") { # max[number[\$2]] = \$3 * 86400 max[number[\$2]] = \$3 } else print "What do I do with '" \$0 "'?" } } END { # if (file == "mtab") { # if (\$3 != "4.2") next # if (index(\$1,"/dev/sr")) next # devname[\$1] = \$2 # namedev[\$2] = \$1 # } if (IGNORE) exit for (i=0;i<=1;i++) { for (dev in devname) { if (ignore[devname[dev]]) continue if (dump[i ":" dev]) { split(dump[i ":" dev],tempa) tdate = tempa[2] tempa[3] tempa[5] if (! then[tdate] ) jd tempa[1] " " tempa[2] " " tempa[3] " " tempa[4] " dev " tempa[5] | getline then[tdate] interval = now - then[tdate] # tcmd = jd tempa[2] " " tempa[3] " " tempa[4] " " zone " " tempa[5] # tcmd | getline then close(tcmd) # interval = now - then # if ((interval >= max[i]) && ! ignore[i ":" dev]) print "Last",type[i],"of",devname[dev],"was",tempa[2],tempa[3],tempa[5],"at",tempa[4],"(" int(interval / 86400) " days)" if ((interval >= max[i]) && ! ignore[i ":" dev]) print "Last",type[i],"of",devname[dev],"was",tempa[1],tempa[2],tempa[3],tempa[5],"at",tempa[4],"(" interval " days)" } else if (! ignore[i ":" dev]) print "No",type[i],"ever done for",devname[dev] } } } EOF $NAWK -f $TMP.nawk /etc/dumpdates $RCFILE done: /bin/rm -rf $TMP.all $TMP.err $TMP.nawk $TMP.out $TMP.unique exit Sample .cbackupsrc follows: # This is the rc file for cbackups. # Two sorts of commands go here: maximum and ignore. # "maximum" defines how many days *not* to report on undone dumps of # this sort, eg, # maximum full 7 # or # maximum incremental 2 # (It is recommended that 2 be specified for incrementals, since they # are not done on days with fulls.) # "ignore" defines what structures, or hosts to ignore. # You can ignore just one type of dump on one host: # ignore aramis /usr incremental # one structure on one host: # ignore aramis /export/swap # one type of dump on one type of structure on all hosts: # ignore /export/root incremental # one structure on all hosts: # ignore /tmp # or a host entirely: # ignore aramis # set up full and incremental limits maximum full 8 maximum incremental 3 # structures to be ignored completely ignore /export/swap ignore /fac/free ignore /mnt ignore /swapfiles ignore /tmp # hosts to be ignored completely ignore arc ignore bismith ignore zap # structures to ignore on specific hosts ignore planchet /export/swap ignore parallel / ignore parallel /usr ignore parallel /var ignore parallel /local ignore parallel /opt # incrementals to be ignored ignore apical / incremental ignore apical /usr incremental