Added to the repository

This commit is contained in:
Sergey Poznyakoff
2004-05-06 09:14:51 +00:00
parent 0273b1ae09
commit 6c4dc180dd
3 changed files with 655 additions and 0 deletions

256
scripts/backup.in Normal file
View File

@@ -0,0 +1,256 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright 2004, Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 1, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
. ${LIBPATH-@libexecdir@}/backup.sh
now() {
#IF_DATE_FORMAT_OK
date +%Y-%m-%d
#ELSE_DATE_FORMAT_OK
LC_ALL=C date | \
sed 's/[^ ]* *\([^ ]*\) *\([^ ]*\).* \([^ ]*\)$/\3-\1-\2/
/-[0-9]$/s/\([0-9]\)$/0\1/
/Jan/{s/Jan/01/p;q;}
/Feb/{s/Feb/02/p;q;}
/Mar/{s/Mar/03/p;q;}
/Apr/{s/Apr/04/p;q;}
/May/{s/May/05/p;q;}
/Jun/{s/Jun/06/p;q;}
/Jul/{s/Jul/07/p;q;}
/Aug/{s/Aug/08/p;q;}
/Sep/{s/Sep/09/p;q;}
/Oct/{s/Oct/10/p;q;}
/Nov/{s/Nov/11/p;q;}
/Dec/{s/Dec/12/p;q;}'
#ENDIF_DATE_FORMAT_OK
}
DUMP_LEVEL=0
TIME=
usage() {
cat - <<EOF
usage: $PROGNAME [OPTIONS] [WHEN]
Options are:
-l, --level LEVEL Do backup level LEVEL (default $DUMP_LEVEL).
-f, --force Force backup even if today's log file already
exists.
-v, --verbose LEVEL Set verbosity level.
-t, --time TIME Wait till TIME, then do backup.
Informational options:
-h, --help Display this help message.
-l, --license Display program license.
-V, --version Display program version.
Optional argumen WHEN is for backward compatibility only. It has been
superseded by --time option.
TIME argument can be one of:
now -- do backup immediately.
HH -- do backup at HH hours.
HH:MM -- do backup at HH:MM.
Send bug reports to @PACKAGE_BUGREPORT@.
EOF
}
# For compatibility with previous versions, deduce the backup level
# from the command name
case "$PROGNAME" in
level-[0-9]) DUMP_LEVEL=`expr $PROGNAME : 'level-\([0-9][0-9]*\)'`;;
esac
while [ $# -ne 0 ];
do
case $1 in
-l|--l|--le|--lev|--leve|--level)
shift
DUMP_LEVEL=$1
;;
-v|--verb|--verbo|--verbos|--verbose)
shift
VERBOSE=$1
;;
-V|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "backup; @PACKAGE@ (@VERSION@)"
exit 0;;
-L|--li|--lic|--lice|--licen|--licens|--license)
license
exit;;
-t|--ti|--tim|--time)
shift
TIME=$1
;;
-f|--f|--fo|--for|--forc|--force)
FORCE=yes
;;
-h|--h|--he|--hel|--help)
usage
exit;;
*) if [ "x$TIME" != "x" ]; then
bailout "Extra argument. Try $PROGNAME --help for more info."
else
TIME=$1
fi;;
esac
shift
done
if [ "x$TIME" = x ]; then
bailout "No backup time specified. Try $PROGNAME --help for more info."
exit 1
fi
init_backup
# Maybe sleep until around specified or default hour.
wait_time $TIME
if [ $DUMP_LEVEL -ne 0 ]; then
PREV_LEVEL=`expr $DUMP_LEVEL - 1`
PREV_DATE=`ls -t ${LOGPATH}/log-*-level-$PREV_LEVEL|
head -1|
sed "s,${LOGPATH}/log-\(.*\)-level.*,\1,"`
if [ "x$PREV_DATE" = x ]; then
bailout "Can't determine date of the previous backup"
fi
message 0 "Backup from $PREV_DATE to $NOW"
fi
# start doing things
# Make sure the log file did not already exist. Create it.
if [ "x$FORCE" = "xyes" ]; then
rm ${LOGFILE}
fi
if [ -f "${LOGFILE}" ] ; then
bailout "Log file ${LOGFILE} already exists."
else
touch "${LOGFILE}"
fi
message 1 "Ready for backup."
message 10 "TAR invocation: $TAR_PART1"
message 20 "Variables:"
message 20 "BACKUP_DIRS=$BACKUP_DIRS"
message 20 "BACKUP_FILES=$BACKUP_FILES"
# The buch of commands below is run in a subshell for which all output is
# piped through `tee' to the logfile. Doing this, instead of having
# multiple pipelines all over the place, is cleaner and allows access to
# the exit value from various commands more easily.
(
message 1 "preparing tapes"
$MT_BEGIN "${TAPE_FILE}"
rm -f "${VOLNO_FILE}"
message 1 "processing backup directories"
set - ${BACKUP_DIRS}
while [ $# -ne 0 ] ; do
date="`date`"
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
remotehost="`expr \"${1}\" : '\([^/][^/]*\):.*'`"
if [ -z "$remotehost" ]; then
remotehost=$localhost
fi
echo "Backing up ${1} at ${date}"
message 10 "fs=$fs"
message 10 "fsname=$fsname"
message 10 "remotehost=$remotehost"
if [ $DUMP_LEVEL -eq 0 ]; then
make_level_log ${remotehost}
else
LF=`level_log_name ${fsname} 0`
pdate=`remote_run "${remotehost}" ls -l $LF | awk '{
printf("%s", $6)
for (i=7;i<NF;i++)
printf(" %s", $i)
print "" }'`
echo "Last `prev_level` dump on this filesystem was on $pdate"
remote_run "${remotehost}" cp $LF "`level_log_name temp`"
fi
backup_host ${remotehost} \
"--listed=`level_log_name temp`" \
"--label='`print_level` backup of ${fs} on ${remotehost} at ${date}'" \
-C ${fs} .
# `rsh' doesn't exit with the exit status of the remote command. What
# stupid lossage. TODO: think of a reliable workaround.
if [ $? -ne 0 ] ; then
echo "Backup of ${1} failed." 1>&2
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
flush_level_log ${remotehost} ${fsname}
fi
${MT_STATUS}
echo "sleeping ${SLEEP_TIME} seconds"
sleep ${SLEEP_TIME}
shift
done
# Dump any individual files requested.
if [ "x${BACKUP_FILES}" != "x" ] ; then
message 1 "processing individual files"
date="`date`"
make_level_log $localhost
echo "Backing up miscellaneous files at ${date}"
backup_host $localhost \
"--listed=`level_log_name temp`"\
"--label='`print_level` backup of miscellaneous files at ${date}'" \
${BACKUP_FILES}
if [ $? -ne 0 ] ; then
echo "Backup of miscellaneous files failed."
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
flush_level_log $localhost
fi
${MT_STATUS}
else
echo "No miscellaneous files specified"
fi
message 1 "final cleanup"
$MT_REWIND "${TAPE_FILE}"
$MT_OFFLINE "${TAPE_FILE}"
) 2>&1 | tee -a "${LOGFILE}"
echo "Sending the dump log to ${ADMINISTRATOR}"
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
# eof

291
scripts/backup.sh Normal file
View File

@@ -0,0 +1,291 @@
#! /bin/sh
# This program is part of GNU tar
# Copyright 2004, Free Software Foundation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 1, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
PROGNAME=`basename $0`
CONFIGPATH="$SYSCONFDIR/backup"
REMOTEBACKUPDIR="$SYSCONFDIR/tar-backup"
CONFIGFILE=${CONFIGPATH}/backup-specs
DIRLIST=${CONFIGPATH}/dirs
FILELIST=${CONFIGPATH}/files
LOGPATH=${CONFIGPATH}/log
LIBPATH=/usr/libexec/backup
# Default functions for running various magnetic tape commands
mt_begin() {
mt -f "$1" retension
}
mt_rewind() {
mt -f "$1" rewind
}
mt_offline() {
mt -f "$1" offl
}
mt_status() {
mt -f "$1" status
}
# The main configuration file may override any of these variables
MT_BEGIN=mt_begin
MT_REWIND=mt_rewind
MT_OFFLINE=mt_offl
MT_STATUS=mt_status
# Insure `mail' is in PATH.
PATH="/usr/ucb:${PATH}"
export PATH
# Put startdate in the subject line of mailed report, since if it happens
# to run longer than 24 hours (as may be the case if someone forgets to put
# in the next volume of the tape in adequate time), the backup date won't
# appear too misleading.
startdate="`date`"
here="`pwd`"
# Save local hostname
localhost="`hostname | sed -e 's/\..*//' | tr A-Z a-z`"
# Produce a diagnostic output
message() {
if [ "$VERBOSE" != "" ]; then
if [ $VERBOSE -ge $1 ]; then
shift
echo "$@"
fi
fi
}
# Bail out and exit.
bailout() {
echo "$PROGNAME: $*" >&2
exit 1
}
# Bail out if we don't have root privileges.
test_root() {
if [ ! -w / ]; then
bailout "The backup must be run as root or else some files will fail to be dumped."
fi
}
advice() {
echo "Directory $1 is not found." >&2
cat >&2 <<EOF
The following directories and files are needed for the backup to function:
1. Directory with configuration files and file lists:
$CONFIGPATH
2. Directory for backup log files
$LOGPATH
3. Main configuration file
$CONFIGFILE
Please, create these and invoke the script again.
EOF
}
init_backup() {
# Check if the necessary directories exist
if [ ! -d $CONFIGPATH ]; then
advice $CONFIGPATH
exit 1
fi
if [ ! -d $LOGPATH ]; then
if mkdir $LOGPATH; then
:
else
advice $LOGPATH
exit 1
fi
fi
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
if [ ! -r $CONFIGFILE ]; then
echo "$PROGNAME: cannot read $CONFIGFILE. Stop." >&2
exit 1
fi
. $CONFIGFILE
# Environment sanity check
test_root
if [ x"${ADMINISTRATOR}" = x ]; then
bailout "ADMINISTRATOR not defined"
fi
[ x"$TAR" = x ] && TAR=tar
[ x"$SLEEP_TIME" = x ] && SLEEP_TIME=60
if [ x$VOLNO_FILE = x ]; then
bailout "VOLNO_FILE not specified"
fi
if [ -r $DIRLIST ]; then
BACKUP_DIRS="$BACKUP_DIRS `cat $DIRLIST`"
fi
if [ -r $FILELIST ]; then
BACKUP_FILES="$BACKUP_FILES `cat $FILELIST`"
fi
if [ \( x"$BACKUP_DIRS" = x \) -a \( x"$BACKUP_FILES" = x \) ]; then
bailout "Neither BACKUP_DIRS nor BACKUP_FILES specified"
fi
TAR_PART1="${TAR} -c --format=gnu --multi-volume --one-file-system --sparse --volno-file=${VOLNO_FILE}"
if [ "x$XLIST" != x ]; then
TAR_PART1="${TAR_PART1} \`test -r $REMOTEBACKUPDIR/$XLIST && echo \"--exclude-from $REMOTEBACKUPDIR/$XLIST\"\`"
fi
if [ "$RSH_COMMAND" != "" ]; then
TAR_PART1="${TAR_PART1} --rsh-command=$RSH_COMMAND"
fi
if [ "$RSH" = "" ]; then
RSH=rsh
fi
if [ x$BLOCKING != x ]; then
TAR_PART1="${TAR_PART1} --blocking=${BLOCKING}"
fi
# Only use --info-script if DUMP_REMIND_SCRIPT was defined in backup-specs
if [ "x${DUMP_REMIND_SCRIPT}" != "x" ]; then
TAR_PART1="${TAR_PART1} --info-script='${DUMP_REMIND_SCRIPT}'"
fi
# Set logfile name
# Logfile name should be in the form ``log-1993-03-18-level-0''
# They go in the directory `@sysconfdir@/log'.
# i.e. year-month-date. This format is useful for sorting by name, since
# logfiles are intentionally kept online for future reference.
LOGFILE="${LOGPATH}/log-`now`-level-${DUMP_LEVEL}"
POSIXLY_CORRECT=1
export POSIXLY_CORRECT
}
wait_time() {
if [ "${1}" != "now" ]; then
if [ "${1}x" != "x" ]; then
spec="${1}"
else
spec="${BACKUP_HOUR}"
fi
pausetime="`date | awk -v spec=\"${spec}\" '
BEGIN {
split(spec, time, ":")
}
{
split($4, now, ":")
diff = 3600 * (time[1] - now[1]) + 60 * (time[2] - now[2]);
if (diff < 0)
diff += 3600 * 24
print diff
}'`"
clear
echo "${SLEEP_MESSAGE}"
sleep "${pausetime}"
fi
}
level_log_name() {
echo "$REMOTEBACKUPDIR/${1}.level-${2-$DUMP_LEVEL}"
}
# Prepare a temporary level logfile
# usage: make_level_log HOSTNAME
make_level_log() {
if [ "z${localhost}" != "z$1" ] ; then
$RSH "$1" mkdir $REMOTEBACKUPDIR > /dev/null 2>&1
$RSH "$1" rm -f `level_log_name temp`
else
mkdir $REMOTEBACKUPDIR > /dev/null 2>&1
rm -f `level_log_name temp`
fi
}
# Rename temporary log
# usage: flush_level_log HOSTNAME FSNAME
flush_level_log() {
message 10 "RENAME: `level_log_name temp` --> `level_log_name $2`"
if [ "z${localhost}" != "z$1" ] ; then
$RSH "$1" mv -f `level_log_name temp` "`level_log_name $2`"
else
mv -f `level_log_name temp` "`level_log_name $2`"
fi
}
# Do actual backup on a host
# usage: backup_host HOSTNAME [TAR_ARGUMENTS]
backup_host() {
message 10 "ARGS: $@"
rhost=$1
shift
if [ "z${localhost}" != "z$rhost" ] ; then
$RSH "$rhost" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" $@
else
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
CMD="exec ${TAR_PART1} -f \"${TAPE_FILE}\" $@"
message 10 "CMD: $CMD"
sh -c "$CMD"
message 10 "RC: $?"
fi
}
print_level() {
if [ ${1-$DUMP_LEVEL} -eq 0 ]; then
echo "Full"
else
echo "Level ${1-$DUMP_LEVEL}"
fi
}
prev_level() {
print_level `expr $DUMP_LEVEL - 1` | tr A-Z a-z
}
remote_run() {
rhost=$1
shift
message 10 "REMOTE $1: $@"
if [ "x$rhost" != "x${localhost}" ] ; then
$RSH "${rhost}" "$@"
else
$*
fi
}
license() {
cat - <<EOF
This program is part of GNU tar
Copyright 2004, Free Software Foundation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
EOF
}

108
scripts/dump-remind.in Normal file
View File

@@ -0,0 +1,108 @@
#!/bin/sh
# This file is included in the GNU tar distribution as an example. It is
# not used by default unless the proper line is uncommented in backup-specs.
# System administrators will probably want to customize this and
# backup-specs for their site.
#
# This script should be run by tar with --info-script (-F) to inform
# interested parties that a tape for the next volume of the backup needs to
# be put in the tape drive.
#
# Include location of `sendmail' and GNU finger.
PATH="/usr/lib:/usr/local/gnubin:${PATH}"
export PATH
# Load library routines
SYSCONFDIR=${SYSCONFDIR-@sysconfdir@}
. ${LIBPATH-@libexecdir@}/backup.sh
MT_REWIND
MT_OFFLINE
volno="`cat \"${VOLNO_FILE}\" 2> /dev/null`"
if [ $? -ne 0 ]; then
volno=0
fi
# Get a list of people to whom to mail a request for changing the tape.
# This egregious nightmare parses the output from GNU finger which shows
# which users are logged into consoles (and thus in the office and capable
# of changing tapes).
#
# Certain users (like `root') aren't real users, and shouldn't be notified.
# Neither should `zippy', `elvis', etc. (on the GNU machines) since they're
# just test accounts.
recipients="`
finger .clients 2> /dev/null \
| sed -ne '
1{
/clientstatus: file has not changed in/{
n;n;n;n;d
}
n;n;d
}
s/^..................................................//
$!{/^$/d
/^root?*$/d
/^zippy$/d
/^fnord$/d
/^elvis$/d
/^snurd$/d
H
}
${g
: 1
s/\(\n\)\([A-Za-z0-9_][A-Za-z0-9_]*\)\(\n.*\)\2\(.*\)/\1\2\3\4/g
s/\n$//g
t 1
s/^\n//
s/\n$//g
s/\n/, /g
: 2
s/, ,/,/g
t 2
p
}'`"
# Customized behavior for FSF machines, to bring attention to the fact that
# the tape needs to be changed (who looks at the terminal?)
sendmail -oi -t << __EOF__
From: `basename $0` (backup tape-changing reminder)
To: ${recipients}
Cc: ${ADMINISTRATOR}
Subject: Backup needs new tape for volume ${volno}
Reply-To: ${ADMINISTRATOR}
This is an automated report from the backup script running on
`hostname`.
Volume ${volno} of the backup needs to be put in the tape drive. Usually
whoever prepared the backup leaves labeled tapes on top of the drive
itself. If there aren't any more, information about where to find tapes
and how to label them are posted on the wall by apple-gunkies (unhelpfully
obscured by a bookshelf). An online copy (which is probably more
up-to-date) can also be found in ~friedman/etc/fsf/backup.how.
__EOF__
echo "Please put volume ${volno} in tape drive and press RETURN"
read input
echo "Writing volume ${volno}..."
sendmail -oi -t << __EOF__
From: `basename $0` (backup tape-changing reminder)
To: ${recipients}
Cc: ${ADMINISTRATOR}
Subject: Volume ${volno} for backup has been added
Reply-To: ${ADMINISTRATOR}
This is an automated report from the backup script running on
`hostname`.
The backup has been continued, so for now no further attention is required.
__EOF__
exit 0
# eof