Merge pull request #137 from zertrin/rework-logging
Big rework of logging handling. Add a --quiet option to suppress most output
This commit is contained in:
commit
cddd3f3c74
1 changed files with 196 additions and 135 deletions
|
|
@ -71,9 +71,12 @@ echo "USAGE:
|
|||
--backup-script automatically backup the script and secret key(s) to
|
||||
the current working directory
|
||||
|
||||
-q, --quiet silence most of output messages, except errors and output
|
||||
that is intended for interactive usage. Silenced output
|
||||
is still logged in the logfile.
|
||||
|
||||
-n, --dry-run perform a trial run with no changes made
|
||||
-d, --debug echo duplicity commands to logfile
|
||||
|
||||
-V, --version print version information about this script and duplicity
|
||||
|
||||
CURRENT SCRIPT VARIABLES:
|
||||
|
|
@ -83,7 +86,7 @@ echo "USAGE:
|
|||
EXCLIST (directories excluded) = ${EXCLIST[*]:0}
|
||||
ROOT (root directory of backup) = ${ROOT}
|
||||
LOGFILE (log file path) = ${LOGFILE}
|
||||
"
|
||||
" >&4
|
||||
}
|
||||
|
||||
DUPLICITY="$(which duplicity)"
|
||||
|
|
@ -93,7 +96,6 @@ if [ ! -x "${DUPLICITY}" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
version(){
|
||||
# Read the version string from the file VERSION
|
||||
VERSION=$(<VERSION)
|
||||
|
|
@ -106,7 +108,7 @@ version(){
|
|||
# Some expensive argument parsing that allows the script to
|
||||
# be insensitive to the order of appearance of the options
|
||||
# and to handle correctly option parameters that are optional
|
||||
while getopts ":c:t:bfvelsndV-:" opt; do
|
||||
while getopts ":c:t:bfvelsqndV-:" opt; do
|
||||
case $opt in
|
||||
# parse long options (a bit tricky because builtin getopts does not
|
||||
# manage long options and I don't want to impose GNU getopt dependancy)
|
||||
|
|
@ -152,6 +154,9 @@ while getopts ":c:t:bfvelsndV-:" opt; do
|
|||
OPTIND=$(( OPTIND + 1 )) # we found it, move forward in arg parsing
|
||||
fi
|
||||
;;
|
||||
quiet)
|
||||
QUIET=1
|
||||
;;
|
||||
dry-run)
|
||||
DRY_RUN="--dry-run "
|
||||
;;
|
||||
|
|
@ -175,6 +180,7 @@ while getopts ":c:t:bfvelsndV-:" opt; do
|
|||
e) COMMAND="cleanup";;
|
||||
l) COMMAND="list-current-files";;
|
||||
s) COMMAND="collection-status";;
|
||||
q) QUIET=1;;
|
||||
n) DRY_RUN="--dry-run ";; # dry run
|
||||
d) ECHO=$(which echo);; # debug
|
||||
V) version;;
|
||||
|
|
@ -188,8 +194,11 @@ while getopts ":c:t:bfvelsndV-:" opt; do
|
|||
;;
|
||||
esac
|
||||
done
|
||||
#echo "Options parsed. COMMAND=${COMMAND}" # for debugging
|
||||
|
||||
|
||||
# ---------------- Read config file if specified -----------------
|
||||
|
||||
# Read config file if specified
|
||||
if [ ! -z "${CONFIG}" ] && [ -f "${CONFIG}" ];
|
||||
then
|
||||
# shellcheck source=duplicity-backup.conf.example
|
||||
|
|
@ -200,6 +209,101 @@ else
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# ----------------------- Setup logging ---------------------------
|
||||
|
||||
# Setup logging as soon as possible, in order to be able to perform i/o redirection
|
||||
|
||||
[[ ${LOGDIR} = "/home/foobar_user_name/logs/test2/" ]] && config_sanity_fail "LOGDIR must be configured"
|
||||
|
||||
# Ensure a trailing slash always exists in the log directory name
|
||||
LOGDIR="${LOGDIR%/}/"
|
||||
|
||||
LOGFILE="${LOGDIR}${LOG_FILE}"
|
||||
|
||||
if [ ! -d "${LOGDIR}" ]; then
|
||||
echo "Attempting to create log directory ${LOGDIR} ..."
|
||||
if ! mkdir -p "${LOGDIR}"; then
|
||||
echo "Log directory ${LOGDIR} could not be created by this user: ${USER}" >&2
|
||||
echo "Aborting..." >&2
|
||||
exit 1
|
||||
else
|
||||
echo "Directory ${LOGDIR} successfully created."
|
||||
fi
|
||||
echo "Attempting to change owner:group of ${LOGDIR} to ${LOG_FILE_OWNER} ..."
|
||||
if ! chown "${LOG_FILE_OWNER}" "${LOGDIR}"; then
|
||||
echo "User ${USER} could not change the owner:group of ${LOGDIR} to ${LOG_FILE_OWNER}" >&2
|
||||
echo "Aborting..." >&2
|
||||
exit 1
|
||||
else
|
||||
echo "Directory ${LOGDIR} successfully changed to owner:group of ${LOG_FILE_OWNER}"
|
||||
fi
|
||||
elif [ ! -w "${LOGDIR}" ]; then
|
||||
echo "Log directory ${LOGDIR} is not writeable by this user: ${USER}" >&2
|
||||
echo "Aborting..." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# -------------------- Setup I/O redirections --------------------
|
||||
# Magic from
|
||||
# http://superuser.com/questions/86915/force-bash-script-to-use-tee-without-piping-from-the-command-line
|
||||
#
|
||||
# ##### Redirection matrix in the case when quiet mode is ON #####
|
||||
#
|
||||
# QUIET mode ON | shown on screen | not shown on screen
|
||||
# ---------------+-----------------+----------------------
|
||||
# logged | fd2, fd3 | fd1, fd5
|
||||
# not logged | fd4 | -
|
||||
#
|
||||
# ##### Redirection matrix in the case when quiet mode is OFF #####
|
||||
#
|
||||
# QUIET mode OFF | shown on screen | not shown on screen
|
||||
# ---------------+-----------------+----------------------
|
||||
# logged | fd1, fd2, fd3 | fd5
|
||||
# not logged | fd4 | -
|
||||
#
|
||||
# fd1 is stdout and is always logged but only shown if not QUIET
|
||||
# fd2 is stderr and is always shown on screen and logged
|
||||
# fd3 is like stdout but always shown on screen (for interactive prompts)
|
||||
# fd4 is always shown on sceen but never logged (for the usage text)
|
||||
# fd5 is never shown on screen but always logged (for delimiters in the log)
|
||||
#
|
||||
|
||||
# make a backup of stderr for later
|
||||
exec 6>&2
|
||||
|
||||
# fd2 and fd3 are always logged and shown on screen via tee
|
||||
# for fd2 (original stderr) the output of tee needs to be redirected to stderr
|
||||
exec 2> >(tee -ia "${LOGFILE}" >&2)
|
||||
# create fd3 as a redirection to stdout and the logfile via tee
|
||||
exec 3> >(tee -ia "${LOGFILE}")
|
||||
|
||||
# create fd4 as a copy of stdout, but that won't be redirected to tee
|
||||
# so that it is always shown and never logged
|
||||
exec 4>&1
|
||||
|
||||
# create fd5 as a direct redirection to the logfile
|
||||
# so that the content is never shown on screen but always logged
|
||||
exec 5>> "${LOGFILE}"
|
||||
|
||||
# finally we modify stdout (fd1) to always being logged (like fd3 and fd5)
|
||||
# but only being shown on screen if quiet mode is not active
|
||||
if [[ ${QUIET} == 1 ]]; then
|
||||
# Quiet mode: stdout not shown on screen but still logged via fd5
|
||||
exec 1>&5
|
||||
else
|
||||
# Normal mode: stdout shown on screen and logged via fd3
|
||||
exec 1>&3
|
||||
fi
|
||||
|
||||
# tests for debugging the magic
|
||||
#echo "redirected to fd1"
|
||||
#echo "redirected to fd2" >&2
|
||||
#echo "redirected to fd3" >&3
|
||||
#echo "redirected to fd4" >&4
|
||||
#echo "redirected to fd5" >&5
|
||||
|
||||
# ------------------------- Setting up variables ------------------------
|
||||
|
||||
STATIC_OPTIONS="${DRY_RUN}${STATIC_OPTIONS}"
|
||||
|
||||
SIGN_PASSPHRASE=${PASSPHRASE}
|
||||
|
|
@ -223,11 +327,6 @@ if [[ -n "${TMPDIR}" ]]; then
|
|||
export TMPDIR
|
||||
fi
|
||||
|
||||
# Ensure a trailing slash always exists in the log directory name
|
||||
LOGDIR="${LOGDIR%/}/"
|
||||
|
||||
LOGFILE="${LOGDIR}${LOG_FILE}"
|
||||
|
||||
# File to use as a lock. The lock is used to insure that only one instance of
|
||||
# the script is running at a time.
|
||||
LOCKFILE=${LOGDIR}backup.lock
|
||||
|
|
@ -311,7 +410,8 @@ config_sanity_fail()
|
|||
{
|
||||
EXPLANATION=$1
|
||||
CONFIG_VAR_MSG="Oops!! ${0} was unable to run!\nWe are missing one or more important variables in the configuration file.\nCheck your configuration because it appears that something has not been set yet."
|
||||
echo -e "${CONFIG_VAR_MSG}\n ${EXPLANATION}."
|
||||
echo -e "${CONFIG_VAR_MSG}\n ${EXPLANATION}." >&2
|
||||
echo -e "--------------------- END ---------------------\n" >&5
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
|
@ -325,7 +425,6 @@ check_variables ()
|
|||
${GPG_SIGN_KEY} = "foobar_gpg_key" || \
|
||||
${PASSPHRASE} = "foobar_gpg_passphrase")) ]] && \
|
||||
config_sanity_fail "ENCRYPTION is set to 'yes', but GPG_ENC_KEY, GPG_SIGN_KEY, or PASSPHRASE have not been configured"
|
||||
[[ ${LOGDIR} = "/home/foobar_user_name/logs/test2/" ]] && config_sanity_fail "LOGDIR must be configured"
|
||||
[[ ( ${DEST_IS_S3} = true && (${AWS_ACCESS_KEY_ID} = "foobar_aws_key_id" || ${AWS_SECRET_ACCESS_KEY} = "foobar_aws_access_key" )) ]] && \
|
||||
config_sanity_fail "An s3 DEST has been specified, but AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY have not been configured"
|
||||
[[ ( ${DEST_IS_GS} = true && (${GS_ACCESS_KEY_ID} = "foobar_gcs_key_id" || ${GS_SECRET_ACCESS_KEY} = "foobar_gcs_secret_id" )) ]] && \
|
||||
|
|
@ -333,32 +432,6 @@ check_variables ()
|
|||
[[ ! -z "${INCEXCFILE}" && ! -f ${INCEXCFILE} ]] && config_sanity_fail "The specified INCEXCFILE ${INCEXCFILE} does not exists"
|
||||
}
|
||||
|
||||
check_logdir()
|
||||
{
|
||||
if [ ! -d "${LOGDIR}" ]; then
|
||||
echo "Attempting to create log directory ${LOGDIR} ..."
|
||||
if ! mkdir -p "${LOGDIR}"; then
|
||||
echo "Log directory ${LOGDIR} could not be created by this user: ${USER}"
|
||||
echo "Aborting..."
|
||||
exit 1
|
||||
else
|
||||
echo "Directory ${LOGDIR} successfully created."
|
||||
fi
|
||||
echo "Attempting to change owner:group of ${LOGDIR} to ${LOG_FILE_OWNER} ..."
|
||||
if ! chown "${LOG_FILE_OWNER}" "${LOGDIR}"; then
|
||||
echo "User ${USER} could not change the owner:group of ${LOGDIR} to ${LOG_FILE_OWNER}"
|
||||
echo "Aborting..."
|
||||
exit 1
|
||||
else
|
||||
echo "Directory ${LOGDIR} successfully changed to owner:group of ${LOG_FILE_OWNER}"
|
||||
fi
|
||||
elif [ ! -w "${LOGDIR}" ]; then
|
||||
echo "Log directory ${LOGDIR} is not writeable by this user: ${USER}"
|
||||
echo "Aborting..."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
mailcmd_sendmail() {
|
||||
# based on http://linux.die.net/man/8/sendmail.sendmail
|
||||
echo -e "From: ${EMAIL_FROM}\nSubject: ${EMAIL_SUBJECT}\n" | cat - "${LOGFILE}" | ${MAILCMD} "${EMAIL_TO}"
|
||||
|
|
@ -396,7 +469,7 @@ email_logfile()
|
|||
MAILCMD_BASENAME=${MAILCMD_REALPATH##*/}
|
||||
|
||||
if [ ! -x "${MAILCMD}" ]; then
|
||||
echo -e "Email couldn't be sent. ${MAIL} not available." >> "${LOGFILE}"
|
||||
echo -e "Email couldn't be sent. ${MAIL} not available." >&2
|
||||
else
|
||||
EMAIL_SUBJECT=${EMAIL_SUBJECT:="duplicity-backup ${BACKUP_STATUS:-"ERROR"} [${HOSTNAME}] ${LOG_FILE}"}
|
||||
case ${MAIL} in
|
||||
|
|
@ -424,7 +497,7 @@ email_logfile()
|
|||
mailcmd_else;;
|
||||
esac
|
||||
|
||||
echo -e "Email notification sent to ${EMAIL_TO} using ${MAIL}" >> "${LOGFILE}"
|
||||
echo -e "Email notification sent to ${EMAIL_TO} using ${MAIL}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
|
@ -435,32 +508,32 @@ send_notification()
|
|||
if [ ! -z "${NOTIFICATION_SERVICE}" ]; then
|
||||
if [ "${NOTIFICATION_SERVICE}" = "slack" ]; then
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"${NOTIFICATION_CONTENT}\", \"channel\": \"${SLACK_CHANNEL}\", \"username\": \"${SLACK_USERNAME}\", \"icon_emoji\": \":${SLACK_EMOJI}:\"}" "${SLACK_HOOK_URL}"
|
||||
echo -e "Slack notification sent to channel ${SLACK_CHANNEL}" >> "${LOGFILE}"
|
||||
echo -e "Slack notification sent to channel ${SLACK_CHANNEL}"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "ifttt" ]; then
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"value1\": \"${NOTIFICATION_CONTENT}\", \"value2\": \"${IFTTT_VALUE2}\"}" "${IFTTT_HOOK_URL}"
|
||||
echo -e "IFTTT notification sent to Maker channel event ${IFTTT_EVENT}" >> "${LOGFILE}"
|
||||
echo -e "IFTTT notification sent to Maker channel event ${IFTTT_EVENT}"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "pushover" ]; then
|
||||
curl -s \
|
||||
-F "token=${PUSHOVER_TOKEN}" \
|
||||
-F "user=${PUSHOVER_USER}" \
|
||||
-F "message=${NOTIFICATION_CONTENT}" \
|
||||
https://api.pushover.net/1/messages
|
||||
echo -e "Pushover notification sent" >> "${LOGFILE}"
|
||||
echo -e "Pushover notification sent"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
get_lock()
|
||||
{
|
||||
echo "Attempting to acquire lock ${LOCKFILE}" >> "${LOGFILE}"
|
||||
echo "Attempting to acquire lock ${LOCKFILE}" >&5
|
||||
if ( set -o noclobber; echo "$$" > "${LOCKFILE}" ) 2> /dev/null; then
|
||||
# The lock succeeded. Create a signal handler to remove the lock file when the process terminates.
|
||||
trap 'EXITCODE=$?; echo "Removing lock. Exit code: ${EXITCODE}" >>${LOGFILE}; rm -f "${LOCKFILE}"' 0
|
||||
echo "successfully acquired lock." >> "${LOGFILE}"
|
||||
trap 'EXITCODE=$?; echo "Removing lock. Exit code: ${EXITCODE}" >> ${LOGFILE}; rm -f "${LOCKFILE}"' EXIT
|
||||
echo "successfully acquired lock." >&5
|
||||
else
|
||||
# Write lock acquisition errors to log file and stderr
|
||||
echo "lock failed, could not acquire ${LOCKFILE}" | tee -a "${LOGFILE}" >&2
|
||||
echo "lock held by $(cat "${LOCKFILE}")" | tee -a "${LOGFILE}" >&2
|
||||
echo "lock failed, could not acquire ${LOCKFILE}" >&2
|
||||
echo "lock held by $(cat "${LOCKFILE}")" >&2
|
||||
email_logfile
|
||||
send_notification
|
||||
exit 2
|
||||
|
|
@ -469,7 +542,7 @@ get_lock()
|
|||
|
||||
get_source_file_size()
|
||||
{
|
||||
echo "-----------[ Source Disk Use Information ]-----------" >> "${LOGFILE}"
|
||||
echo "-----------[ Source Disk Use Information ]-----------"
|
||||
|
||||
# FIXME: doesn't work properly with include/exclude-filelists (issue #101)
|
||||
|
||||
|
|
@ -483,7 +556,7 @@ get_source_file_size()
|
|||
DUEXCFLAG="-I -"
|
||||
;;
|
||||
OpenBSD)
|
||||
echo "WARNING: OpenBSD du does not support exclusion, sizes may be off" >> "${LOGFILE}"
|
||||
echo "WARNING: OpenBSD du does not support exclusion, sizes may be off"
|
||||
DUEXCFLAG=""
|
||||
;;
|
||||
*)
|
||||
|
|
@ -508,11 +581,10 @@ get_source_file_size()
|
|||
for include in "${DUINCLIST[@]}"; do
|
||||
echo -e "${DUEXCLIST}" | \
|
||||
du -hs ${DUEXCFLAG} "${include}" | \
|
||||
awk '{ FS="\t"; $0=$0; print $1"\t"$2 }' \
|
||||
>> "${LOGFILE}"
|
||||
awk '{ FS="\t"; $0=$0; print $1"\t"$2 }'
|
||||
done
|
||||
|
||||
echo >> "${LOGFILE}"
|
||||
echo
|
||||
|
||||
# Restore IFS
|
||||
IFS=$OLDIFS
|
||||
|
|
@ -520,7 +592,7 @@ get_source_file_size()
|
|||
|
||||
get_remote_file_size()
|
||||
{
|
||||
echo "---------[ Destination Disk Use Information ]--------" >> "${LOGFILE}"
|
||||
echo "---------[ Destination Disk Use Information ]--------"
|
||||
FRIENDLY_TYPE_NAME=""
|
||||
dest_type=$(echo "${DEST}" | cut -c 1,2)
|
||||
case $dest_type in
|
||||
|
|
@ -531,8 +603,8 @@ get_remote_file_size()
|
|||
TMPDEST="${DEST%/${TMPDEST}}"
|
||||
ssh_opt=$(echo "${STATIC_OPTIONS}" |awk -vo="--ssh-options=" '{s=index($0,o); if (s) {s=substr($0,s+length(o)); m=substr(s,0,1); for (i=2; i < length(s); i++) { if (substr(s,i,1) == m && substr(s,i-1,1) != "\\\\") break; } print substr(s,2,i-2)}}')
|
||||
|
||||
SIZE=$(${TMPDEST%://*} "${ssh_opt}" "${TMPDEST#*//}" du -hs "${DEST#${TMPDEST}/}" | awk '{print $1}') 2>> "${LOGFILE}"
|
||||
EMAIL_SUBJECT="${EMAIL_SUBJECT} ${SIZE} $(${TMPDEST%://*} "${ssh_opt}" "${TMPDEST#*//}" df -hP "${DEST#${TMPDEST}/}" | awk '{tmp=$5 " used"}END{print tmp}')" 2>> "${LOGFILE}"
|
||||
SIZE=$(${TMPDEST%://*} "${ssh_opt}" "${TMPDEST#*//}" du -hs "${DEST#${TMPDEST}/}" | awk '{print $1}')
|
||||
EMAIL_SUBJECT="${EMAIL_SUBJECT} ${SIZE} $(${TMPDEST%://*} "${ssh_opt}" "${TMPDEST#*//}" df -hP "${DEST#${TMPDEST}/}" | awk '{tmp=$5 " used"}END{print tmp}')"
|
||||
;;
|
||||
"fi")
|
||||
FRIENDLY_TYPE_NAME="File"
|
||||
|
|
@ -572,12 +644,12 @@ get_remote_file_size()
|
|||
esac
|
||||
|
||||
if [[ ${FRIENDLY_TYPE_NAME} ]] ; then
|
||||
echo -e "${SIZE}\t${FRIENDLY_TYPE_NAME} type backend" >> "${LOGFILE}"
|
||||
echo -e "${SIZE}\t${FRIENDLY_TYPE_NAME} type backend"
|
||||
else
|
||||
echo "Destination disk use information is currently only available for the following storage backends:" >> "${LOGFILE}"
|
||||
echo "File, SSH, Amazon S3 and Google Cloud" >> "${LOGFILE}"
|
||||
echo "Destination disk use information is currently only available for the following storage backends:"
|
||||
echo "File, SSH, Amazon S3 and Google Cloud"
|
||||
fi
|
||||
echo >> "${LOGFILE}"
|
||||
echo
|
||||
}
|
||||
|
||||
include_exclude()
|
||||
|
|
@ -629,27 +701,27 @@ include_exclude()
|
|||
|
||||
duplicity_cleanup()
|
||||
{
|
||||
echo "----------------[ Duplicity Cleanup ]----------------" >> "${LOGFILE}"
|
||||
echo "----------------[ Duplicity Cleanup ]----------------"
|
||||
if [[ "${CLEAN_UP_TYPE}" != "none" && ! -z ${CLEAN_UP_TYPE} && ! -z ${CLEAN_UP_VARIABLE} ]]; then
|
||||
{
|
||||
eval "${ECHO}" "${DUPLICITY}" "${CLEAN_UP_TYPE}" "${CLEAN_UP_VARIABLE}" "${STATIC_OPTIONS}" --force \
|
||||
"${ENCRYPT}" \
|
||||
"${DEST}" >> "${LOGFILE}"
|
||||
"${DEST}"
|
||||
} || {
|
||||
BACKUP_ERROR=1
|
||||
}
|
||||
echo >> "${LOGFILE}"
|
||||
echo
|
||||
fi
|
||||
if [ ! -z "${REMOVE_INCREMENTALS_OLDER_THAN}" ] && [[ ${REMOVE_INCREMENTALS_OLDER_THAN} =~ ^[0-9]+$ ]]; then
|
||||
{
|
||||
eval "${ECHO}" "${DUPLICITY}" remove-all-inc-of-but-n-full "${REMOVE_INCREMENTALS_OLDER_THAN}" \
|
||||
"${STATIC_OPTIONS}" --force \
|
||||
"${ENCRYPT}" \
|
||||
"${DEST}" >> "${LOGFILE}"
|
||||
"${DEST}"
|
||||
} || {
|
||||
BACKUP_ERROR=1
|
||||
}
|
||||
echo >> "${LOGFILE}"
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -662,8 +734,7 @@ duplicity_backup()
|
|||
"${EXCLUDE}" \
|
||||
"${INCLUDE}" \
|
||||
"${EXCLUDEROOT}" \
|
||||
"${ROOT}" "${DEST}" \
|
||||
>> "${LOGFILE}"
|
||||
"${ROOT}" "${DEST}"
|
||||
} || {
|
||||
BACKUP_ERROR=1
|
||||
}
|
||||
|
|
@ -673,8 +744,7 @@ duplicity_cleanup_failed()
|
|||
{
|
||||
{
|
||||
eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
|
||||
"${DEST}" \
|
||||
>> "${LOGFILE}"
|
||||
"${DEST}"
|
||||
} || {
|
||||
BACKUP_ERROR=1
|
||||
}
|
||||
|
|
@ -683,9 +753,9 @@ duplicity_cleanup_failed()
|
|||
setup_passphrase()
|
||||
{
|
||||
if [ ! -z "${GPG_ENC_KEY}" ] && [ ! -z "${GPG_SIGN_KEY}" ] && [ "${GPG_ENC_KEY}" != "${GPG_SIGN_KEY}" ]; then
|
||||
echo -n "Please provide the passphrase for decryption (GPG key 0x${GPG_ENC_KEY}): "
|
||||
echo -n "Please provide the passphrase for decryption (GPG key 0x${GPG_ENC_KEY}): " >&3
|
||||
builtin read -s -r ENCPASSPHRASE
|
||||
echo -ne "\n"
|
||||
echo -ne "\n" >&3
|
||||
PASSPHRASE=${ENCPASSPHRASE}
|
||||
export PASSPHRASE
|
||||
fi
|
||||
|
|
@ -695,24 +765,6 @@ get_file_sizes()
|
|||
{
|
||||
get_source_file_size
|
||||
get_remote_file_size
|
||||
|
||||
case $(uname) in
|
||||
FreeBSD|Darwin|DragonFly)
|
||||
sed -i '' -e '/^--*$/d' "${LOGFILE}"
|
||||
;;
|
||||
OpenBSD)
|
||||
ed -s "${LOGFILE}" <<-"EOF"
|
||||
g/^--*$/d
|
||||
w
|
||||
q
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
sed -i -e '/^--*$/d' "${LOGFILE}"
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ -n "${LOG_FILE_OWNER}" ]] && chown "${LOG_FILE_OWNER}" "${LOGFILE}"
|
||||
}
|
||||
|
||||
backup_this_script()
|
||||
|
|
@ -727,35 +779,36 @@ backup_this_script()
|
|||
TMPFILENAME=${TMPDIR}.tar.gpg
|
||||
README=${TMPDIR}/README
|
||||
|
||||
echo "You are backing up: "
|
||||
echo " 1. ${SCRIPTPATH}"
|
||||
echo "You are backing up: " >&3
|
||||
echo " 1. ${SCRIPTPATH}" >&3
|
||||
|
||||
if [ ! -z "${GPG_ENC_KEY}" ] && [ ! -z "${GPG_SIGN_KEY}" ]; then
|
||||
if [ "${GPG_ENC_KEY}" = "${GPG_SIGN_KEY}" ]; then
|
||||
echo " 2. GPG Secret encryption and sign key: ${GPG_ENC_KEY}"
|
||||
echo " 2. GPG Secret encryption and sign key: ${GPG_ENC_KEY}" >&3
|
||||
else
|
||||
echo " 2. GPG Secret encryption key: ${GPG_ENC_KEY} and GPG secret sign key: ${GPG_SIGN_KEY}"
|
||||
echo " 2. GPG Secret encryption key: ${GPG_ENC_KEY} and GPG secret sign key: ${GPG_SIGN_KEY}" >&3
|
||||
fi
|
||||
else
|
||||
echo " 2. GPG Secret encryption and sign key: none (symmetric encryption)"
|
||||
echo " 2. GPG Secret encryption and sign key: none (symmetric encryption)" >&3
|
||||
fi
|
||||
|
||||
if [ ! -z "${CONFIG}" ] && [ -f "${CONFIG}" ];
|
||||
then
|
||||
echo " 3. Config file: ${CONFIG}"
|
||||
echo " 3. Config file: ${CONFIG}" >&3
|
||||
fi
|
||||
|
||||
if [ ! -z "${INCEXCFILE}" ] && [ -f "${INCEXCFILE}" ];
|
||||
then
|
||||
echo " 4. Include/Exclude globbing file: ${INCEXCFILE}"
|
||||
echo " 4. Include/Exclude globbing file: ${INCEXCFILE}" >&3
|
||||
fi
|
||||
|
||||
echo "Backup tarball will be encrypted and saved to: $(pwd)/${TMPFILENAME}"
|
||||
echo
|
||||
echo ">> Are you sure you want to do that ('yes' to continue)?"
|
||||
echo "Backup tarball will be encrypted and saved to: $(pwd)/${TMPFILENAME}" >&3
|
||||
echo >&3
|
||||
echo ">> Are you sure you want to do that ('yes' to continue)?" >&3
|
||||
read -r ANSWER
|
||||
if [ "${ANSWER}" != "yes" ]; then
|
||||
echo "You said << ${ANSWER} >> so I am exiting now."
|
||||
echo "You said << ${ANSWER} >> so I am exiting now." >&3
|
||||
echo -e "--------------------- END ---------------------\n" >&5
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -784,19 +837,22 @@ backup_this_script()
|
|||
fi
|
||||
|
||||
echo -e "${README_TXT}" > "${README}"
|
||||
echo "Encrypting tarball, choose a password you'll remember..."
|
||||
echo "Encrypting tarball, choose a password you'll remember..." >&3
|
||||
tar -cf - "${TMPDIR}" | gpg -aco "${TMPFILENAME}"
|
||||
rm -Rf "${TMPDIR}"
|
||||
echo -e "\nIMPORTANT!!"
|
||||
echo ">> To restore these files, run the following (remember your password):"
|
||||
echo "gpg -d ${TMPFILENAME} | tar -xf -"
|
||||
echo -e "\nYou may want to write the above down and save it with the file."
|
||||
echo -e "\nIMPORTANT!!" >&3
|
||||
echo ">> To restore these files, run the following (remember your password):" >&3
|
||||
echo "gpg -d ${TMPFILENAME} | tar -xf -" >&3
|
||||
echo -e "\nYou may want to write the above down and save it with the file." >&3
|
||||
}
|
||||
|
||||
check_variables
|
||||
check_logdir
|
||||
# ##################################################
|
||||
# #### end of functions definition ####
|
||||
# ##################################################
|
||||
|
||||
echo -e "-------- START DUPLICITY-BACKUP SCRIPT for ${HOSTNAME} --------\n" >> "${LOGFILE}"
|
||||
check_variables
|
||||
|
||||
echo -e "-------- START DUPLICITY-BACKUP SCRIPT for ${HOSTNAME} --------\n" >&5
|
||||
|
||||
get_lock
|
||||
|
||||
|
|
@ -807,7 +863,7 @@ EXCLUDEROOT=
|
|||
case "${COMMAND}" in
|
||||
"backup-script")
|
||||
backup_this_script
|
||||
exit
|
||||
exit 0
|
||||
;;
|
||||
|
||||
"full")
|
||||
|
|
@ -824,11 +880,12 @@ case "${COMMAND}" in
|
|||
DEST=${OLDROOT}
|
||||
OPTION="verify"
|
||||
|
||||
echo -e "-------[ Verifying Source & Destination ]-------\n" >> "${LOGFILE}"
|
||||
echo -e "-------[ Verifying Source & Destination ]-------\n"
|
||||
include_exclude
|
||||
setup_passphrase
|
||||
echo -e "Attempting to verify now ..."
|
||||
echo -e "Attempting to verify now ...\n" >&3
|
||||
duplicity_backup
|
||||
echo
|
||||
|
||||
OLDROOT=${ROOT}
|
||||
ROOT=${DEST}
|
||||
|
|
@ -836,7 +893,7 @@ case "${COMMAND}" in
|
|||
|
||||
get_file_sizes
|
||||
|
||||
echo -e "Verify complete. Check the log file for results:\n>> ${LOGFILE}"
|
||||
echo -e "Verify complete.\n" >&3
|
||||
;;
|
||||
|
||||
"cleanup")
|
||||
|
|
@ -846,11 +903,11 @@ case "${COMMAND}" in
|
|||
STATIC_OPTIONS="--force"
|
||||
fi
|
||||
|
||||
echo -e "-------[ Cleaning up Destination ]-------\n" >> "${LOGFILE}"
|
||||
echo -e "-------[ Cleaning up Destination ]-------\n"
|
||||
setup_passphrase
|
||||
duplicity_cleanup_failed
|
||||
|
||||
echo -e "Cleanup complete." >> "${LOGFILE}"
|
||||
echo -e "Cleanup complete."
|
||||
;;
|
||||
|
||||
"restore")
|
||||
|
|
@ -861,15 +918,16 @@ case "${COMMAND}" in
|
|||
fi
|
||||
|
||||
if [[ ! "${RESTORE_DEST}" ]]; then
|
||||
echo "Please provide a destination path (eg, /home/user/dir):"
|
||||
echo "Please provide a destination path (eg, /home/user/dir):" >&3
|
||||
read -r -e NEWDESTINATION
|
||||
DEST=${NEWDESTINATION}
|
||||
echo ">> You will restore from ${ROOT} to ${DEST}"
|
||||
echo "Are you sure you want to do that ('yes' to continue)?"
|
||||
echo ">> You will restore from ${ROOT} to ${DEST}" >&3
|
||||
echo "Are you sure you want to do that ('yes' to continue)?" >&3
|
||||
read -r ANSWER
|
||||
if [[ "${ANSWER}" != "yes" ]]; then
|
||||
echo "You said << ${ANSWER} >> so I am exiting now."
|
||||
echo -e "User aborted restore process ...\n" >> "${LOGFILE}"
|
||||
echo "You said << ${ANSWER} >> so I am exiting now." >&3
|
||||
echo -e "User aborted restore process ...\n" >&2
|
||||
echo -e "--------------------- END ---------------------\n" >&5
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
|
|
@ -877,7 +935,7 @@ case "${COMMAND}" in
|
|||
fi
|
||||
|
||||
setup_passphrase
|
||||
echo "Attempting to restore now ..."
|
||||
echo "Attempting to restore now ..." >&3
|
||||
duplicity_backup
|
||||
;;
|
||||
|
||||
|
|
@ -890,8 +948,8 @@ case "${COMMAND}" in
|
|||
fi
|
||||
|
||||
if [[ ! "${FILE_TO_RESTORE}" ]]; then
|
||||
echo "Which file or directory do you want to restore?"
|
||||
echo "(give the path relative to the root of the backup eg, mail/letter.txt):"
|
||||
echo "Which file or directory do you want to restore?" >&3
|
||||
echo "(give the path relative to the root of the backup eg, mail/letter.txt):" >&3
|
||||
read -r -e FILE_TO_RESTORE
|
||||
echo
|
||||
fi
|
||||
|
|
@ -902,14 +960,15 @@ case "${COMMAND}" in
|
|||
DEST=$(basename "${FILE_TO_RESTORE}")
|
||||
fi
|
||||
|
||||
echo -e "YOU ARE ABOUT TO..."
|
||||
echo -e ">> RESTORE: ${FILE_TO_RESTORE}"
|
||||
echo -e ">> TO: ${DEST}"
|
||||
echo -e "\nAre you sure you want to do that ('yes' to continue)?"
|
||||
echo -e "YOU ARE ABOUT TO..." >&3
|
||||
echo -e ">> RESTORE: ${FILE_TO_RESTORE}" >&3
|
||||
echo -e ">> TO: ${DEST}" >&3
|
||||
echo -e "\nAre you sure you want to do that ('yes' to continue)?" >&3
|
||||
read -r ANSWER
|
||||
if [ "${ANSWER}" != "yes" ]; then
|
||||
echo "You said << ${ANSWER} >> so I am exiting now."
|
||||
echo -e "--------------------- END ---------------------\n" >> "${LOGFILE}"
|
||||
echo "You said << ${ANSWER} >> so I am exiting now." >&3
|
||||
echo -e "User aborted restore process ...\n" >&2
|
||||
echo -e "--------------------- END ---------------------\n" >&5
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -917,7 +976,7 @@ case "${COMMAND}" in
|
|||
DEST="'${DEST}'"
|
||||
|
||||
setup_passphrase
|
||||
echo "Restoring now ..."
|
||||
echo "Restoring now ..." >&3
|
||||
#use INCLUDE variable without creating another one
|
||||
INCLUDE="--file-to-restore ${FILE_TO_RESTORE}"
|
||||
duplicity_backup
|
||||
|
|
@ -933,8 +992,7 @@ case "${COMMAND}" in
|
|||
eval \
|
||||
"${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
|
||||
${ENCRYPT} \
|
||||
"${DEST}" | tee -a "${LOGFILE}"
|
||||
echo -e "--------------------- END ---------------------\n" >> "${LOGFILE}"
|
||||
"${DEST}"
|
||||
;;
|
||||
|
||||
"collection-status")
|
||||
|
|
@ -943,8 +1001,7 @@ case "${COMMAND}" in
|
|||
eval \
|
||||
"${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
|
||||
${ENCRYPT} \
|
||||
"${DEST}" | tee -a "${LOGFILE}"
|
||||
echo -e "--------------------- END ---------------------\n" >> "${LOGFILE}"
|
||||
"${DEST}"
|
||||
;;
|
||||
|
||||
"backup")
|
||||
|
|
@ -955,12 +1012,12 @@ case "${COMMAND}" in
|
|||
;;
|
||||
|
||||
*)
|
||||
echo -e "[Only show $(basename "$0") usage options]\n" >> "${LOGFILE}"
|
||||
echo -e "[Only show $(basename "$0") usage options]\n"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "--------- END DUPLICITY-BACKUP SCRIPT ---------\n" >> "${LOGFILE}"
|
||||
echo -e "--------- END DUPLICITY-BACKUP SCRIPT ---------\n" >&5
|
||||
|
||||
if [ "${BACKUP_ERROR}" ]; then
|
||||
BACKUP_STATUS="ERROR"
|
||||
|
|
@ -990,4 +1047,8 @@ unset PASSPHRASE
|
|||
unset SIGN_PASSPHRASE
|
||||
unset FTP_PASSWORD
|
||||
|
||||
# restore stdout and stderr to their original values
|
||||
# and close the other fd
|
||||
exec 1>&4 2>&6 3>&- 4>&- 5>&- 6>&-
|
||||
|
||||
# vim: set tabstop=2 shiftwidth=2 sts=2 autoindent smartindent:
|
||||
|
|
|
|||
Loading…
Reference in a new issue