1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
#!/bin/sh
#
# Run this script as root on the machine that has the tape drive, to make a
# level-1 dump containing all files changed since the last full dump.
#
# If you give `now' as an argument, the dump is done immediately.
# Otherwise, it waits until 1am.
#
# You must edit the file `backup-specs' to set the parameters for your site.
# Useful for backup-specs, in case things have to be done slightly
# differently for different dump levels.
DUMP_LEVEL=1
# Insure `mail' is in PATH.
PATH="/usr/ucb:${PATH}"
export PATH
# This is not the most reliable test in the world. The following might be
# more predictable:
#
# whoami="`whoami`"
# euid="`sed -ne '/^'\"${whoami}\"':/{s/^[^:]*:[^:]*://;s/:.*//p;q;}' /etc/passwd`"
# if [ "${euid}" != 0 ]; then ...
#
if [ ! -w / ]; then
echo "The backup must be run as root or else some files will fail to be dumped."
exit 1
fi
# Get the values of BACKUP_DIRS, BACKUP_FILES, and other variables.
. ./backup-specs
# Maybe sleep until around specified or default hour.
if [ "z${1}" != "znow" ]; then
if [ "${1}x" != "x" ]; then
spec="${1}"
else
spec="${BACKUP_HOUR}"
fi
pausetime="`date | awk '
{
hr = substr($4, 1, 2);
mn = substr($4, 4, 2);
if((hr + 0) < (spec + 0))
print 3600 * (spec - hr) - 60 * mn;
else
print 3600 * (spec + (24 - hr)) - 60 * mn;
}' spec=\"${spec}\"`"
clear
echo "${SLEEP_MESSAGE}"
sleep "${pausetime}"
fi
# start doing things
# 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`"
# Logfile name should be in the form ``log-1993-03-18-level-1''
# They go in the subdirectory `log' of the current directory.
# i.e. year-month-date. This format is useful for sorting by name, since
# logfiles are intentionally kept online for future reference.
LOGFILE="log/log-`date | sed -ne '
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;}'`-level-${DUMP_LEVEL}"
localhost="`hostname | sed -e 's/\..*//'`"
TAR_PART1="${TAR} -c --multi-volume --one-file-system --blocking=${BLOCKING} --sparse --volno-file=${VOLNO_FILE}"
# 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
# Make sure the log file did not already exist. Create it.
if [ -f "${LOGFILE}" ] ; then
echo "Log file ${LOGFILE} already exists." 1>&2
exit 1
else
touch "${LOGFILE}"
fi
# Most everything below here 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.
(
# Caveat: Some version of `mt' require `-t', not `-f'.
mt -f "${TAPE_FILE}" rewind
rm -f "${VOLNO_FILE}"
set - ${BACKUP_DIRS}
while [ $# -ne 0 ] ; do
date="`date`"
remotehost="`echo \"${1}\" | sed -e 's/:.*$//'`"
fs="`echo \"${1}\" | sed -e 's/^.*://'`"
fsname="`echo \"${1}\" | sed -e 's/\//:/g'`"
# This filename must be absolute; it is opened on the machine that runs tar.
TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
TAR_PART3="--label='level 1 backup of ${fs} on ${remotehost} at ${date}' -C ${fs} ."
echo "Backing up ${1} at ${date}"
echo "Last full dump on this filesystem:"
if [ "z${remotehost}" != "z${localhost}" ] ; then
rsh "${remotehost}" "ls -l /etc/tar-backup/${fsname}.level-0; \
cp /etc/tar-backup/${fsname}.level-0 /etc/tar-backup/temp.level-1"
else
ls -l "/etc/tar-backup/${fsname}.level-0"
cp "/etc/tar-backup/${fsname}.level-0" /etc/tar-backup/temp.level-1
fi
# Actually back things up.
if [ "z${remotehost}" != "z${localhost}" ] ; then
rsh "${remotehost}" ${TAR_PART1} -f "${localhost}:${TAPE_FILE}" ${TAR_PART2} ${TAR_PART3}
else
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3}"
fi
# `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."
# I'm assuming that the tar will have written an empty
# file to the tape, otherwise I should do a cat here.
else
if [ "z${localhost}" != "z${remotehost}" ] ; then
rsh "${remotehost}" mv -f /etc/tar-backup/temp.level-1 "/etc/tar-backup/${fsname}.level-1"
else
mv -f /etc/tar-backup/temp.level-1 "/etc/tar-backup/${fsname}.level-1"
fi
fi
${TAPE_STATUS}
sleep 60
shift
done
# Dump any individual files requested.
if [ "x${BACKUP_FILES}" != "x" ] ; then
date="`date`"
TAR_PART2="--listed=/etc/tar-backup/temp.level-1"
TAR_PART3="--label='Incremental backup of miscellaneous files at ${date}'"
echo "Backing up miscellaneous files at ${date}"
echo "Last full dump of these files:"
ls -l /etc/tar-backup/misc.level-0
rm -f /etc/tar-backup/temp.level-1
cp /etc/tar-backup/misc.level-0 /etc/tar-backup/temp.level-1
# Using `sh -c exec' causes nested quoting and shell substitution
# to be handled here in the same way rsh handles it.
sh -c "exec ${TAR_PART1} -f \"${TAPE_FILE}\" ${TAR_PART2} ${TAR_PART3} ${BACKUP_FILES}"
if [ $? -ne 0 ] ; then
echo "Backup of miscellaneous files 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
mv -f /etc/tar-backup/temp.level-1 /etc/tar-backup/misc.level-1
fi
${TAPE_STATUS}
else
echo "No miscellaneous files specified"
fi
# Caveat: some versions of `mt' use `-t' instead of `-f'.
mt -f "${TAPE_FILE}" rewind
mt -f "${TAPE_FILE}" offl
) 2>&1 | tee -a "${LOGFILE}"
echo "Sending the dump log to ${ADMINISTRATOR}"
mail -s "Results of backup started ${startdate}" ${ADMINISTRATOR} < "${LOGFILE}"
# eof
|