Merge commit 'john/updates'

Fixed alot of conflicts due to parallel work, but it looks very good now!

Conflicts:
	ccollect.sh
This commit is contained in:
Nico Schottelius 2009-07-24 09:09:16 +02:00
commit 2b890b0316
2 changed files with 108 additions and 46 deletions

View file

@ -1,19 +1,19 @@
#!/bin/sh #!/bin/sh
# #
# 2005-2009 Nico Schottelius (nico-ccollect at schottelius.org) # 2005-2009 Nico Schottelius (nico-ccollect at schottelius.org)
# #
# This file is part of ccollect. # This file is part of ccollect.
# #
# ccollect is free software: you can redistribute it and/or modify # ccollect is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# ccollect is distributed in the hope that it will be useful, # ccollect is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with ccollect. If not, see <http://www.gnu.org/licenses/>. # along with ccollect. If not, see <http://www.gnu.org/licenses/>.
# #
@ -178,7 +178,6 @@ fi
[ -d "${CCOLLECT_CONF}" ] || _exit_err "No configuration found in " \ [ -d "${CCOLLECT_CONF}" ] || _exit_err "No configuration found in " \
"\"${CCOLLECT_CONF}\" (is \$CCOLLECT_CONF properly set?)" "\"${CCOLLECT_CONF}\" (is \$CCOLLECT_CONF properly set?)"
# #
# Create (portable!) source "array" # Create (portable!) source "array"
# #
@ -231,14 +230,6 @@ if [ -x "${CPREEXEC}" ]; then
[ "${ret}" -eq 0 ] || _exit_err "${CPREEXEC} failed. Aborting" [ "${ret}" -eq 0 ] || _exit_err "${CPREEXEC} failed. Aborting"
fi fi
#
# check default configuration
#
D_FILE_INTERVAL="${CDEFAULTS}/intervals/${INTERVAL}"
D_INTERVAL="$(cat "${D_FILE_INTERVAL}" 2>/dev/null)"
# #
# Let's do the backup # Let's do the backup
# #
@ -277,6 +268,21 @@ while [ "${i}" -lt "${no_sources}" ]; do
c_dest="${backup}/destination" c_dest="${backup}/destination"
c_pre_exec="${backup}/pre_exec" c_pre_exec="${backup}/pre_exec"
c_post_exec="${backup}/post_exec" c_post_exec="${backup}/post_exec"
for opt in exclude verbose very_verbose rsync_options summary delete_incomplete \
remote_host rsync_failure_codes mtime quiet_if_down ; do
if [ -f "${backup}/$opt" -o -f "${backup}/no_$opt" ]; then
eval c_$opt=\"${backup}/$opt\"
else
eval c_$opt=\"${CDEFAULTS}/$opt\"
fi
done
#
# With mtime option, sort backup directories with mtime (default is ctime)
#
if [ -f "$c_mtime" ] ; then
TSORT="t"
fi
# #
# Marking backups: If we abort it's not removed => Backup is broken # Marking backups: If we abort it's not removed => Backup is broken
@ -328,19 +334,6 @@ while [ "${i}" -lt "${no_sources}" ]; do
fi fi
fi fi
#
# interval definition: First try source specific, fallback to default
#
c_interval="$(cat "${backup}/intervals/${INTERVAL}" 2>/dev/null)"
if [ -z "${c_interval}" ]; then
c_interval="${D_INTERVAL}"
if [ -z "${c_interval}" ]; then
_exit_err "No definition for interval \"${INTERVAL}\" found. Skipping."
fi
fi
# #
# Source checks # Source checks
# #
@ -356,7 +349,14 @@ while [ "${i}" -lt "${no_sources}" ]; do
# #
# Verify source is up and accepting connections before deleting any old backups # Verify source is up and accepting connections before deleting any old backups
# #
rsync "${source}" >/dev/null || _exit_err "Source ${source} is not readable. Skipping." if ! rsync "${source}" >/dev/null 2>"${TMP}" ; then
if [ -f "${c_quiet_if_down}" ]; then
_exit_err "Source ${source} is not readable. Skipping."
else
cat "${TMP}"
_exit_err "Error: source ${source} is not readable. Skipping."
fi
fi
# #
# Destination is a path # Destination is a path
@ -394,12 +394,12 @@ while [ "${i}" -lt "${no_sources}" ]; do
# - insert ccollect default parameters # - insert ccollect default parameters
# - insert options # - insert options
# - insert user options # - insert user options
# #
# rsync standard options # rsync standard options
# #
set -- "$@" "--archive" "--delete" "--numeric-ids" "--relative" \ set -- "$@" "--archive" "--delete" "--numeric-ids" "--relative" \
"--delete-excluded" "--sparse" "--delete-excluded" "--sparse"
# #
# exclude list # exclude list
@ -438,7 +438,7 @@ while [ "${i}" -lt "${no_sources}" ]; do
# #
# Check for incomplete backups # Check for incomplete backups
# #
pcmd ls -1 "${ddir}/${INTERVAL}"*".${c_marker}" 2>/dev/null | while read marker; do pcmd ls -1 "${ddir}/"*".${c_marker}" 2>/dev/null | while read marker; do
incomplete="$(echo ${marker} | sed "s/\\.${c_marker}\$//")" incomplete="$(echo ${marker} | sed "s/\\.${c_marker}\$//")"
_techo "Incomplete backup: ${incomplete}" _techo "Incomplete backup: ${incomplete}"
if [ -f "${c_delete_incomplete}" ]; then if [ -f "${c_delete_incomplete}" ]; then
@ -450,6 +450,19 @@ while [ "${i}" -lt "${no_sources}" ]; do
fi fi
done done
#
# interval definition: First try source specific, fallback to default
#
c_interval="$(cat "${backup}/intervals/${INTERVAL}" 2>/dev/null)"
if [ -z "${c_interval}" ]; then
c_interval="$(cat "${CDEFAULTS}/intervals/${INTERVAL}" 2>/dev/null)"
if [ -z "${c_interval}" ]; then
_exit_err "No definition for interval \"${INTERVAL}\" found. Skipping."
fi
fi
# #
# check if maximum number of backups is reached, if so remove # check if maximum number of backups is reached, if so remove
# use grep and ls -p so we only look at directories # use grep and ls -p so we only look at directories
@ -458,7 +471,7 @@ while [ "${i}" -lt "${no_sources}" ]; do
| sed 's/^ *//g')" || _exit_err "Counting backups failed" | sed 's/^ *//g')" || _exit_err "Counting backups failed"
_techo "Existing backups: ${count} Total keeping backups: ${c_interval}" _techo "Existing backups: ${count} Total keeping backups: ${c_interval}"
if [ "${count}" -ge "${c_interval}" ]; then if [ "${count}" -ge "${c_interval}" ]; then
substract="$((${c_interval} - 1))" substract="$((${c_interval} - 1))"
remove="$((${count} - ${substract}))" remove="$((${count} - ${substract}))"
@ -487,12 +500,9 @@ while [ "${i}" -lt "${no_sources}" ]; do
# #
# Check for backup directory to clone from: Always clone from the latest one! # Check for backup directory to clone from: Always clone from the latest one!
# #
# Use ls -1c instead of -1t, because last modification maybe the same on all
# and metadate update (-c) is updated by rsync locally.
#
last_dir="$(pcmd ls -${TSORT}p1 "${ddir}" | grep '/$' | head -n 1)" || \ last_dir="$(pcmd ls -${TSORT}p1 "${ddir}" | grep '/$' | head -n 1)" || \
_exit_err "Failed to list contents of ${ddir}." _exit_err "Failed to list contents of ${ddir}."
# #
# clone from old backup, if existing # clone from old backup, if existing
# #
@ -500,7 +510,7 @@ while [ "${i}" -lt "${no_sources}" ]; do
set -- "$@" "--link-dest=${ddir}/${last_dir}" set -- "$@" "--link-dest=${ddir}/${last_dir}"
_techo "Hard linking from ${last_dir}" _techo "Hard linking from ${last_dir}"
fi fi
# set time when we really begin to backup, not when we began to remove above # set time when we really begin to backup, not when we began to remove above
destination_date="$(${CDATE})" destination_date="$(${CDATE})"
destination_dir="${ddir}/${INTERVAL}.${destination_date}.$$" destination_dir="${ddir}/${INTERVAL}.${destination_date}.$$"
@ -523,16 +533,36 @@ while [ "${i}" -lt "${no_sources}" ]; do
# #
_techo "Transferring files..." _techo "Transferring files..."
rsync "$@" "${source}" "${destination_full}"; ret=$? rsync "$@" "${source}" "${destination_full}"; ret=$?
#
# remove marking here
#
pcmd rm "${destination_dir}.${c_marker}" || \
_exit_err "Removing ${destination_dir}/${c_marker} failed."
_techo "Finished backup (rsync return code: $ret)." _techo "Finished backup (rsync return code: $ret)."
if [ "${ret}" -ne 0 ]; then
_techo "Warning: rsync exited non-zero, the backup may be broken (see rsync errors)." #
# Set modification time (mtime) to current time
#
pcmd touch "${destination_dir}"
#
# Check if rsync exit code indicates failure.
#
fail=""
if [ -f "$c_rsync_failure_codes" ]; then
while read code ; do
if [ "$ret" = "$code" ]; then
fail=1
fi
done <"$c_rsync_failure_codes"
fi
#
# Remove marking here unless rsync failed.
#
if [ -z "$fail" ]; then
pcmd rm "${destination_dir}.${c_marker}" || \
_exit_err "Removing ${destination_dir}/${c_marker} failed."
if [ "${ret}" -ne 0 ]; then
_techo "Warning: rsync exited non-zero, the backup may be broken (see rsync errors)."
fi
else
_techo "Warning: rsync failed with return code $ret."
fi fi
# #

View file

@ -21,7 +21,7 @@ Supported and tested operating systems and architectures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`ccollect` was successfully tested on the following platforms: `ccollect` was successfully tested on the following platforms:
- GNU/Linux on amd64/hppa/i386/ppc - GNU/Linux on amd64/hppa/i386/ppc/ARM
- FreeBSD on amd64/i386 - FreeBSD on amd64/i386
- Mac OS X 10.5 - Mac OS X 10.5
- NetBSD on alpha/amd64/i386/sparc/sparc64 - NetBSD on alpha/amd64/i386/sparc/sparc64
@ -359,6 +359,9 @@ Additionally a source may have the following files:
- `delete_incomplete` delete incomplete backups - `delete_incomplete` delete incomplete backups
- `remote_host` host to backup to - `remote_host` host to backup to
- `rsync_failure_codes` list of rsync exit codes that indicate complete failure
- `mtime` Sort backup directories based on their modification time
- `quiet_if_down` Suppress error messages if source is not connectable
Example: Example:
@ -574,6 +577,35 @@ If you create the file `delete_incomplete` in a source specification directory,
was interrupted) and remove them. Without this file `ccollect` will only warn was interrupted) and remove them. Without this file `ccollect` will only warn
the user. the user.
Detailed description of "rsync_failure_codes"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have the file `rsync_failure_codes` in your source configuration
directory, it should contain a newline-separated list of numbers representing
rsync exit codes. If rsync exits with any code in this list, a marker will
be left in the destination directory indicating failure of this backup. If
you have enabled delete_incomplete, then this backup will be deleted during
the next ccollect run on the same interval.
Detailed description of "mtime"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, ccollect.sh chooses the most recent backup directory for cloning or
the oldest for deletion based on the directory's last change time (ctime).
With this option, the sorting is done based on modification time (mtime). With
this version of ccollect.sh, the ctime and mtime of your backups will normally
be the same and this option has no effect. However, if you, for example, move
your backups to another hard disk using cp -a or rsync -a, you should use this
option because the ctimes are not preserved during such operations.
If you have any backups in your repository made with ccollect version 0.7.1 or
earlier, do not use this option.
Detailed description of "quiet_if_down"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, ccollect.sh emits a series of error messages if a source is not
connectable. With this option enabled, ccollect.sh still reports that the
source is not connectable but the associated error messages generated by
rsync or ssh are suppressed. You may want to use this option for sources,
like notebook PCs, that are often disconnected.
Hints Hints
----- -----