Compare commits

..

No commits in common. "010ab1dcebbd38e17ddf08b7659d0ab3854afd5b" and "e4cd29fd42e9f89b5a3c3525e0cfa47f3bb4f602" have entirely different histories.

View File

@ -43,31 +43,10 @@ consoleError() {
}
exitError() {
printf "%s[%s] --- %s execution completed with error ---\n%s" "$err" "$(stamp)" "$scriptName" "$norm" >> "$logfile"
printf "%s[%s] --- %s execution completed with error ---\n%s" "$err" "$(stamp)" "$scriptName" "$norm" >>"$logfile"
exit "$1"
}
doRestore() {
sourceFiles=$(find "${backupLocation}" -iname "${1}" -type d)
if [ -n "$sourceFiles" ]; then
if [ "$verbose" -eq 1 ]; then
if (! (cd "$sourceFiles/_data" && tar -cf - .) | (cd "${2}" && tar xvf -) >> "$logfile" ); then
return 1
else
return 0
fi
else
if (! (cd "$sourceFiles/_data" && tar -cf - .) | (cd "${3}" && tar xvf -) ); then
return 1
else
return 0
fi
fi
else
return 2
fi
}
scriptHelp() {
textNewline
printf "%sUsage: %s [parameters]%s\n\n" "$bold" "$scriptName" "$norm"
@ -104,30 +83,31 @@ textNewline() {
}
trapExit() {
printf "%s[%s] -- [ERROR] 99: Caught signal --%s\n" "$err" "$(stamp)" "$norm" >> "$logfile"
printf "%s[%s] --- %s execution terminated via signal ---\n%s" "$err" "$(stamp)" "$scriptName" "$norm" >> "$logfile"
printf "%s[%s] -- [ERROR] 99: Caught signal --%s\n" "$err" "$(stamp)" "$norm" >>"$logfile"
cleanup
printf "%s[%s] --- %s execution terminated via signal ---\n%s" "$err" "$(stamp)" "$scriptName" "$norm" >>"$logfile"
exit 99
}
writeLog() {
if [ "$1" = "task" ]; then
printf "%s[%s] -- [INFO] %s... " "$info" "$(stamp)" "$2" >> "$logfile"
printf "%s[%s] -- [INFO] %s... " "$info" "$(stamp)" "$2" >>"$logfile"
elif [ "$1" = "done" ]; then
if [ -z "$2" ]; then
printf "%sdone%s --\n%s" "$ok" "$info" "$norm" >> "$logfile"
printf "%sdone%s --\n%s" "$ok" "$info" "$norm" >>"$logfile"
elif [ "$2" = "error" ]; then
printf "%sERROR%s --\n%s" "$err" "$info" "$norm" >> "$logfile"
printf "%sERROR%s --\n%s" "$err" "$info" "$norm" >>"$logfile"
elif [ "$2" = "warn" ]; then
printf "%swarning%s --\n%s" "$yellow" "$info" "$norm" >> "$logfile"
printf "%swarning%s --\n%s" "$yellow" "$info" "$norm" >>"$logfile"
fi
elif [ "$1" = "error" ]; then
printf "%s[%s] -- [ERROR] %s: %s --\n%s" "$err" "$(stamp)" "$2" "$3" "$norm" >> "$logfile"
printf "%s[%s] -- [ERROR] %s: %s --\n%s" "$err" "$(stamp)" "$2" "$3" "$norm" >>"$logfile"
elif [ "$1" = "warn" ]; then
printf "%s[%s] -- [WARNING] %s --\n%s" "$yellow" "$(stamp)" "$2" "$norm" >> "$logfile"
printf "%s[%s] -- [WARNING] %s --\n%s" "$yellow" "$(stamp)" "$2" "$norm" >>"$logfile"
elif [ "$1" = "info" ]; then
printf "%s[%s] -- [INFO] %s --\n%s" "$info" "$(stamp)" "$2" "$norm" >> "$logfile"
printf "%s[%s] -- [INFO] %s --\n%s" "$info" "$(stamp)" "$2" "$norm" >>"$logfile"
elif [ "$1" = "success" ]; then
printf "%s[%s] -- [SUCCESS] %s --\n%s" "$ok" "$(stamp)" "$2" "$norm" >> "$logfile"
printf "%s[%s] -- [SUCCESS] %s --\n%s" "$ok" "$(stamp)" "$2" "$norm" >>"$logfile"
fi
}
@ -222,7 +202,7 @@ while [ $# -gt 0 ]; do
-b|--backup-location)
if [ -n "$2" ]; then
if [ -d "$2" ] && [ -n "$( ls -A "$2" )" ]; then
backupLocation="${2%/}"
backupLocation="$2"
shift
else
consoleError '1' "$1: cannot find specified backup location directory or it is empty."
@ -247,7 +227,7 @@ while [ $# -gt 0 ]; do
restoreRspamd=0
;;
*)
printf "\n%sUnknown option: %s\n" "$err" "$1"
printf "\n%Unknown option: %s\n" "$err" "$1"
printf "Use '--help' for valid options.%s\n\n" "$norm"
exit 1
;;
@ -256,13 +236,9 @@ while [ $# -gt 0 ]; do
done
### pre-flight checks
# ensure there's something to do
if [ "$restoreMail" -eq 0 ] && [ "$restoreSQL" -eq 0 ] && [ "$restorePostfix" -eq 0 ] && [ "$restoreRedis" -eq 0 ] && [ "$restoreRedis" -eq 0 ]; then
printf "\n%sAll restore operations skipped -- nothing to do!%s\n\n" "$yellow" "$norm"
exit 0
fi
# set path so checks are valid for this script environment
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# docker installed?
if ! command -v docker >/dev/null; then
consoleError '3' 'docker does not seem to be installed!'
@ -275,12 +251,8 @@ fi
if [ ! -f "$mcDockerCompose" ]; then
consoleError '1' "docker-compose configuration ($mcDockerCompose) cannot be found."
fi
# forgot to set backup location?
if [ -z "$backupLocation" ]; then
consoleError '1' "'--backup-location' cannot be unspecified or null/empty."
fi
# change to mailcow directory so commands execute properly
\cd "${mcConfig%/*}" || consoleError '4' 'Cannot change to mailcow directory as determined from mailcow.conf location.'
\cd ${mcConfig%/*} || consoleError '4' 'Cannot change to mailcow directory as determined from mailcow.conf location.'
### read mailcow.conf and import vars
# shellcheck source=./mailcow.conf.shellcheck
@ -311,7 +283,7 @@ else
fi
fi
# write initial log entries
if ! printf "%s[%s] --- Start %s execution ---\n%s" "$magenta" "$(stamp)" "$scriptName" "$norm" 2>/dev/null >> "$logfile"; then
if ! printf "%s[%s] --- Start %s execution ---\n%s" "$magenta" "$(stamp)" "$scriptName" "$norm" 2>/dev/null >>"$logfile"; then
consoleError '1' "Unable to write to log file ($logfile)"
fi
writeLog 'info' "Log located at $logfile"
@ -342,7 +314,7 @@ if [ "$restoreSQL" -eq 1 ]; then
if [ -n "$sqlBackup" ]; then
# start mysql container if not already running
if ! docker container inspect -f '{{ .State.Running }}' ${COMPOSE_PROJECT_NAME}_mysql-mailcow_1 > /dev/null 2>&1; then
docker-compose up -d mysql-mailcow > /dev/null 2>&1
docker-compose up -d mysql-mailcow
if docker container inspect -f '{{ .State.Running }}' ${COMPOSE_PROJECT_NAME}_mysql-mailcow_1 > /dev/null 2>&1; then
sqlRunning=1
else
@ -366,223 +338,27 @@ if [ "$restoreSQL" -eq 1 ]; then
else
writeLog 'done' 'error'
writeLog 'error' '13' "Something went wrong while trying to restore SQL database. Perhaps try again?"
errorCount=$((errorCount+1))
fi
fi
fi
### stop containers (necessary for all restore operations except SQL)
writeLog 'task' "Stopping mailcow"
if ! docker-compose down --timeout "${dockerStopTimeout}" > /dev/null 2>&1; then
writeLog 'done' 'error'
writeLog 'error' '20' "Unable to bring mailcow containers down -- cannot reliably restore. Aborting."
exitError 20
fi
if [ "$( docker ps --filter "name=${COMPOSE_PROJECT_NAME}" -q | wc -l )" -gt 0 ]; then
writeLog 'done' 'error'
writeLog 'error' '20' "Unable to bring mailcow containers down -- cannot reliably restore. Aborting."
exitError 20
fi
writeLog 'done'
### restore mail and encryption key
if [ "$restoreMail" -eq 1 ]; then
if [ "$verbose" -eq 1 ]; then
writeLog 'info' "Restoring email"
else
writeLog 'task' "Restoring email"
fi
# restore email messages
doRestore "${COMPOSE_PROJECT_NAME}_vmail-vol-1" "$dockerVolumeMail"; ec="$?"
case "$ec" in
0)
if [ "$verbose" -eq 1 ]; then
writeLog 'success' "Email messages restored"
else
writeLog 'done'
fi
;;
1)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '52' "There was an error restoring one or more email messages."
else
writeLog 'done' 'error'
writeLog 'error' '52' "There was an error restoring one or more email messages."
fi
;;
2)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '51' "Cannot locate email message backups!"
else
writeLog 'done' 'error'
writeLog 'error' '51' "Cannot locate email message backups!"
fi
;;
esac
# restore encryption key
doRestore "${COMPOSE_PROJECT_NAME}_crypt-vol-1" "$dockerVolumeCrypt"; ec="$?"
case "$ec" in
0)
if [ "$verbose" -eq 1 ]; then
writeLog 'success' "Encryption key restored"
else
writeLog 'done'
fi
;;
1)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '52' "There was an error restoring the encryption key! Any restored messages are likely *not* readable!"
else
writeLog 'done' 'error'
writeLog 'error' '52' "There was an error restoring the encryption key! Any restored messages are likely *not* readable!"
fi
;;
2)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '51' "Cannot locate encryption key backup!"
else
writeLog 'done' 'error'
writeLog 'error' '51' "Cannot locate encryption key backup!"
fi
;;
esac
fi
### restore postfix
if [ "$restorePostfix" -eq 1 ]; then
if [ "$verbose" -eq 1 ]; then
writeLog 'info' "Restoring postfix files"
else
writeLog 'task' "Restoring postfix files"
fi
# restore email messages
doRestore "${COMPOSE_PROJECT_NAME}_postfix-vol-1" "$dockerVolumePostfix"; ec="$?"
case "$ec" in
0)
if [ "$verbose" -eq 1 ]; then
writeLog 'success' "Postfix files restored"
else
writeLog 'done'
fi
;;
1)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '52' "There was an error restoring one or more postfix files."
else
writeLog 'done' 'error'
writeLog 'error' '52' "There was an error restoring one or more postfix files."
fi
;;
2)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '51' "Cannot locate postfix backups!"
else
writeLog 'done' 'error'
writeLog 'error' '51' "Cannot locate postfix backups!"
fi
;;
esac
fi
### restore rspamd
if [ "$restoreRspamd" -eq 1 ]; then
if [ "$verbose" -eq 1 ]; then
writeLog 'info' "Restoring Rspamd files"
else
writeLog 'task' "Restoring Rspamd files"
fi
# restore email messages
doRestore "${COMPOSE_PROJECT_NAME}_rspamd-vol-1" "$dockerVolumeRspamd"; ec="$?"
case "$ec" in
0)
if [ "$verbose" -eq 1 ]; then
writeLog 'success' "Rspamd files restored"
else
writeLog 'done'
fi
;;
1)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '52' "There was an error restoring one or more Rspamd files."
else
writeLog 'done' 'error'
writeLog 'error' '52' "There was an error restoring one or more Rspamd files."
fi
;;
2)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '51' "Cannot locate Rspamd backups!"
else
writeLog 'done' 'error'
writeLog 'error' '51' "Cannot locate Rspamd backups!"
fi
;;
esac
fi
### restore redis
if [ "$restoreRedis" -eq 1 ]; then
if [ "$verbose" -eq 1 ]; then
writeLog 'info' "Restoring redis database"
else
writeLog 'task' "Restoring redis database"
fi
# restore email messages
doRestore "${COMPOSE_PROJECT_NAME}_redis-vol-1" "$dockerVolumeRedis"; ec="$?"
case "$ec" in
0)
if [ "$verbose" -eq 1 ]; then
writeLog 'success' "Redis database restored"
else
writeLog 'done'
fi
;;
1)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '52' "There was an error restoring the redis database. This is usually *not* a serious issue."
else
writeLog 'done' 'error'
writeLog 'error' '52' "There was an error restoring the redis database. This is usually *not* a serious issue."
fi
;;
2)
if [ "$verbose" -eq 1 ]; then
writeLog 'error' '51' "Cannot locate redis database backups!"
else
writeLog 'done' 'error'
writeLog 'error' '51' "Cannot locate redis database backups!"
fi
;;
esac
fi
### restart mailcow
writeLog 'task' "Starting mailcow"
if ! docker-compose up -d > /dev/null 2>&1; then
writeLog 'done' 'warn'
writeLog 'warn' '21' "Unable to automatically start mailcow containers. Please attempt a manual start and note any errors."
warnCount=$((warnCount+1))
fi
writeLog 'done'
#TODO: stop containers
#TODO: copy backups to correct docker volumes
#TODO: restart docker containers
#TODO: optionally reindex dovecot (parameter)
### exit gracefully
writeLog 'success' "All processes completed"
printf "%s[%s] --- %s execution completed ---\n%s" "$magenta" "$(stamp)" "$scriptName" "$norm" >>"$logfile"
# note non-terminating errors
if [ "$errorCount" -gt 0 ]; then
# note non-terminating errors
printf "%s[%s] --- %s execution completed with %s error(s) ---\n%s" "$err" "$(stamp)" "$scriptName" "$errorCount" "$norm" >> "$logfile"
exit 98
elif [ "$warnCount" -gt 0 ]; then
printf "%s[%s] --- %s execution completed with %s warning(s) ---\n%s" "$yellow" "$(stamp)" "$scriptName" "$warnCount" "$norm" >> "$logfile"
exit 97
else
writeLog 'success' "All processes completed"
printf "%s[%s] --- %s execution completed ---\n%s" "$magenta" "$(stamp)" "$scriptName" "$norm" >> "$logfile"
exit 0
printf "%s%s errors encountered!%s\n" "$err" "$errorCount" "$norm" >>"$logfile"
fi
# note warnings
if [ "$warnCount" -gt 0 ]; then
printf "%s%s warnings issued!%s\n" "$yellow" "$warnCount" "$norm" >>"$logfile"
fi
exit 0
### error codes:
# 1: parameter error
@ -594,14 +370,9 @@ fi
# 11: cannot locate SQL dump in backup directory
# 12: cannot start mysql-mailcow container
# 13: restoring SQL dump was unsuccessful
# 2x: Docker/Docker-Compose errors
# 20: cannot bring docker container(s) down successfully
# 21: cannot bring docker container(s) up successfully
# 5x: File restore errors
# 51: cannot locate source files in backup directory
# 52: error restoring one or more files
# 97: script completed with 1 or more warnings
# 98: script completed with 1 or more non-terminating errors
# 99: TERM signal trapped
# 100: could not change to mailcow-dockerized directory
# 101: could not stop container(s)
# 102: could not start container(s)
#EOF