feat: new error handling

This commit is contained in:
ge 2022-10-08 21:26:08 +03:00
parent a501adfc65
commit 40fb8613be
10 changed files with 98 additions and 108 deletions

View File

@ -18,8 +18,8 @@ help:
@echo ' tests run tests from $(TESTS_DIR)' @echo ' tests run tests from $(TESTS_DIR)'
@echo ' lint run shellcheck' @echo ' lint run shellcheck'
@echo ' manpages build manual pages from $(DOCS_DIR)' @echo ' manpages build manual pages from $(DOCS_DIR)'
@echo ' install install boring-backup with prefix' @echo ' install install boring_backup with prefix'
@echo ' uninstall uninstall boring-backup with prefix' @echo ' uninstall uninstall boring_backup with prefix'
@echo @echo
@echo 'prefix examples: $$HOME/.local, /usr/local, /usr/bin' @echo 'prefix examples: $$HOME/.local, /usr/local, /usr/bin'
@echo See README for more info. @echo See README for more info.
@ -31,7 +31,7 @@ tests:
done done
lint: lint:
shellcheck $(SRC_DIR)/boring-backup shellcheck $(SRC_DIR)/boring_backup
shellcheck $(SRC_DIR)/lib/*.sh shellcheck $(SRC_DIR)/lib/*.sh
shellcheck $(SRC_DIR)/lib/handlers/sources/*.sh shellcheck $(SRC_DIR)/lib/handlers/sources/*.sh
shellcheck $(SRC_DIR)/lib/handlers/targets/*.sh shellcheck $(SRC_DIR)/lib/handlers/targets/*.sh
@ -40,59 +40,59 @@ manpages:
mkdir -pv $(BUILD_DIR)/share/man/ru/man1 mkdir -pv $(BUILD_DIR)/share/man/ru/man1
# See rst2man(1) # See rst2man(1)
# https://docutils.sourceforge.io/docs/index.html # https://docutils.sourceforge.io/docs/index.html
rst2man -v $(DOCS_DIR)/manpages/boring-backup.ru.1.rst \ rst2man -v $(DOCS_DIR)/manpages/boring_backup.ru.1.rst \
> $(BUILD_DIR)/share/man/ru/man1/boring-backup.1 > $(BUILD_DIR)/share/man/ru/man1/boring_backup.1
sed -e 's/.SH NAME/.SH ИМЯ/' \ sed -e 's/.SH NAME/.SH ИМЯ/' \
-e 's/.SH AUTHOR/.SH АВТОРЫ/' \ -e 's/.SH AUTHOR/.SH АВТОРЫ/' \
-e 's/.SH COPYRIGHT/.SH АВТОРСКИЕ ПРАВА/' \ -e 's/.SH COPYRIGHT/.SH АВТОРСКИЕ ПРАВА/' \
-i $(BUILD_DIR)/share/man/ru/man1/boring-backup.1 -i $(BUILD_DIR)/share/man/ru/man1/boring_backup.1
gzip -vf9 $(BUILD_DIR)/share/man/ru/man1/boring-backup.1 gzip -vf9 $(BUILD_DIR)/share/man/ru/man1/boring_backup.1
html: manpages html: manpages
mkdir -p $(BUILD_DIR)/share/doc/boring-backup mkdir -p $(BUILD_DIR)/share/doc/boring_backup
zcat $(BUILD_DIR)/share/man/ru/man1/boring-backup.1.gz | \ zcat $(BUILD_DIR)/share/man/ru/man1/boring_backup.1.gz | \
groff -man -Kutf8 -Thtml \ groff -man -Kutf8 -Thtml \
> $(BUILD_DIR)/share/doc/boring-backup/boring-backup.1.html 2>/dev/null > $(BUILD_DIR)/share/doc/boring_backup/boring_backup.1.html 2>/dev/null
rm -v grohtml-*.png rm -v grohtml-*.png
install: manpages install: manpages
@echo prefix: $$prefix @echo prefix: $$prefix
install -Dm755 $(SRC_DIR)/boring-backup $$prefix/bin/boring-backup install -Dm755 $(SRC_DIR)/boring_backup $$prefix/bin/boring_backup
install -Dm644 $(SRC_DIR)/lib/lib.sh $$prefix/share/boring-backup/lib.sh install -Dm644 $(SRC_DIR)/lib/lib.sh $$prefix/share/boring_backup/lib.sh
install -Dm644 $(SRC_DIR)/lib/backup.sh $$prefix/share/boring-backup/backup.sh install -Dm644 $(SRC_DIR)/lib/backup.sh $$prefix/share/boring_backup/backup.sh
install -Dm644 $(SRC_DIR)/lib/common.sh $$prefix/share/boring-backup/common.sh install -Dm644 $(SRC_DIR)/lib/common.sh $$prefix/share/boring_backup/common.sh
install -Dm644 $(SRC_DIR)/lib/source.sh $$prefix/share/boring-backup/source.sh install -Dm644 $(SRC_DIR)/lib/source.sh $$prefix/share/boring_backup/source.sh
install -Dm644 $(SRC_DIR)/lib/uri.sh $$prefix/share/boring-backup/uri.sh install -Dm644 $(SRC_DIR)/lib/uri.sh $$prefix/share/boring_backup/uri.sh
install -Dm644 $(SRC_DIR)/lib/handlers/sources/tar.sh $$prefix/share/boring-backup/handlers/sources/tar.sh install -Dm644 $(SRC_DIR)/lib/handlers/sources/tar.sh $$prefix/share/boring_backup/handlers/sources/tar.sh
install -Dm644 $(SRC_DIR)/lib/handlers/sources/mysqldump.sh $$prefix/share/boring-backup/handlers/sources/mysqldump.sh install -Dm644 $(SRC_DIR)/lib/handlers/sources/mysqldump.sh $$prefix/share/boring_backup/handlers/sources/mysqldump.sh
install -Dm644 $(SRC_DIR)/lib/handlers/sources/pg_dump.sh $$prefix/share/boring-backup/handlers/sources/pg_dump.sh install -Dm644 $(SRC_DIR)/lib/handlers/sources/pg_dump.sh $$prefix/share/boring_backup/handlers/sources/pg_dump.sh
install -Dm644 $(SRC_DIR)/lib/handlers/targets/cp.sh $$prefix/share/boring-backup/handlers/targets/cp.sh install -Dm644 $(SRC_DIR)/lib/handlers/targets/cp.sh $$prefix/share/boring_backup/handlers/targets/cp.sh
install -Dm644 $(SRC_DIR)/lib/handlers/targets/s3cmd.sh $$prefix/share/boring-backup/handlers/targets/s3cmd.sh install -Dm644 $(SRC_DIR)/lib/handlers/targets/s3cmd.sh $$prefix/share/boring_backup/handlers/targets/s3cmd.sh
sed -e "s%LIBRARY=\"\$${LIBRARY:-.\/lib}\"%LIBRARY=\"\$${LIBRARY:-$$prefix\/share\/boring-backup}\"%" \ sed -e "s%LIBRARY=\"\$${LIBRARY:-.\/lib}\"%LIBRARY=\"\$${LIBRARY:-$$prefix\/share\/boring_backup}\"%" \
-i $$prefix/share/boring-backup/lib.sh \ -i $$prefix/share/boring_backup/lib.sh \
-i $$prefix/bin/boring-backup -i $$prefix/bin/boring_backup
install -Dm664 $(BUILD_DIR)/share/man/ru/man1/boring-backup.1.gz $$prefix/share/man/ru/man1/boring-backup.1.gz install -Dm664 $(BUILD_DIR)/share/man/ru/man1/boring_backup.1.gz $$prefix/share/man/ru/man1/boring_backup.1.gz
uninstall: uninstall:
@echo prefix: $$prefix @echo prefix: $$prefix
rm $$prefix/bin/boring-backup rm $$prefix/bin/boring_backup
rm $$prefix/share/boring-backup/lib.sh rm $$prefix/share/boring_backup/lib.sh
rm $$prefix/share/boring-backup/backup.sh rm $$prefix/share/boring_backup/backup.sh
rm $$prefix/share/boring-backup/common.sh rm $$prefix/share/boring_backup/common.sh
rm $$prefix/share/boring-backup/source.sh rm $$prefix/share/boring_backup/source.sh
rm $$prefix/share/boring-backup/uri.sh rm $$prefix/share/boring_backup/uri.sh
rm $$prefix/share/boring-backup/handlers/sources/tar.sh rm $$prefix/share/boring_backup/handlers/sources/tar.sh
rm $$prefix/share/boring-backup/handlers/sources/mysqldump.sh rm $$prefix/share/boring_backup/handlers/sources/mysqldump.sh
rm $$prefix/share/boring-backup/handlers/sources/pg_dump.sh rm $$prefix/share/boring_backup/handlers/sources/pg_dump.sh
rm $$prefix/share/boring-backup/handlers/targets/cp.sh rm $$prefix/share/boring_backup/handlers/targets/cp.sh
rm $$prefix/share/boring-backup/handlers/targets/s3cmd.sh rm $$prefix/share/boring_backup/handlers/targets/s3cmd.sh
rm -rv $$prefix/share/boring-backup rm -rv $$prefix/share/boring_backup
rm $$prefix/share/man/ru/man1/boring-backup.1.gz rm $$prefix/share/man/ru/man1/boring_backup.1.gz
fixpath: fixpath:
# Set boring-backup library path # Set boring_backup library path
@echo prefix: $$prefix @echo prefix: $$prefix
@echo path: $$path @echo path: $$path
sed -e "s%LIBRARY=\"\$${LIBRARY:-.\/lib}\"%LIBRARY=\"\$${LIBRARY:-$$path}\"%" \ sed -e "s%LIBRARY=\"\$${LIBRARY:-.\/lib}\"%LIBRARY=\"\$${LIBRARY:-$$path}\"%" \
-i $$prefix/share/boring-backup/lib.sh \ -i $$prefix/share/boring_backup/lib.sh \
-i $$prefix/bin/boring-backup -i $$prefix/bin/boring_backup

View File

@ -36,13 +36,13 @@ boring_backup - это расширяемая утилита для резерв
-l, --log-file=\ `файл` -l, --log-file=\ `файл`
Путь до файла лога. Путь до файла лога.
-p, --pid-file=\ `файл`
Путь до PID-файла.
-s, --use-syslog -s, --use-syslog
Записывать лог в syslog вместо файла. Эта опция несовместима с опцией Записывать лог в syslog вместо файла. Эта опция несовместима с опцией
--log-file и переменной log_date_format. --log-file и переменной log_date_format.
-p, --pid-file=\ `файл`
Путь до PID-файла.
ОБЗОР ОБЗОР
----- -----

View File

@ -16,6 +16,9 @@
# 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 this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
set -o pipefail # trace ERR through pipes
set -o errtrace # trace ERR through 'time command' and other functions
VERSION='0.1.0' VERSION='0.1.0'
LIBRARY="${LIBRARY:-./lib}" LIBRARY="${LIBRARY:-./lib}"
@ -29,10 +32,10 @@ else
fi fi
print_help() { print_help() {
printf << EOF \ printf \
"USAGE: "USAGE:
$0 [-hVvs] [-c \033[4mfile\033[0m] [-l \033[4mfile\033[0m] \ %s [-hVvs] [-c \033[4mfile\033[0m] [-l \033[4mfile\033[0m] \
[-p \033[4mfile\033[0m] file ... [-p \033[4mfile\033[0m] file ...
OPTIONS: OPTIONS:
@ -54,19 +57,18 @@ OPTIONS:
-l, --log-file=\033[4mfile\033[0m -l, --log-file=\033[4mfile\033[0m
Log file. Log file.
-p, --pid-file=\033[4mfile\033[0m
PID file. Default: /tmp/boring_backup.pid
-s, --use-syslog -s, --use-syslog
Write log into syslog via logger instead of log file. This option Write log into syslog via logger instead of log file. This option
is incompatible with --log-file option and log_date_format variable. is incompatible with --log-file option and log_date_format variable.
-p, --pid-file=\033[4mfile\033[0m
PID file. Default: /tmp/boring_backup.pid
ENVIRONMENT: ENVIRONMENT:
LIBRARY Path to boring_backup library. Current path is LIBRARY Path to boring_backup library. Current path is
$LIBRARY %s
" " "$0" "$LIBRARY"
EOF
} }
# ---------------------------------------------------------- # # ---------------------------------------------------------- #
@ -132,6 +134,7 @@ while (( "$#" )); do
exit 0 exit 0
;; ;;
-v|--verbose) -v|--verbose)
# shellcheck disable=SC2034
verbose_output=1 verbose_output=1
shift shift
;; ;;
@ -145,15 +148,16 @@ while (( "$#" )); do
log_file="$val" log_file="$val"
shift "$sft" shift "$sft"
;; ;;
-s|--use-syslog)
use_syslog=1
shift
;;
-p|--pid-file|--pid-file=*) -p|--pid-file|--pid-file=*)
optval "$1" "$2" optval "$1" "$2"
pid_file="$val" pid_file="$val"
shift "$sft" shift "$sft"
;; ;;
-s|--use-syslog)
# shellcheck disable=SC2034
use_syslog=1
shift
;;
-*) -*)
echo "Error: Unknown option: $1" >&2 echo "Error: Unknown option: $1" >&2
exit 1 exit 1
@ -175,11 +179,14 @@ if ! declare -F -- log > /dev/null 2>&1; then
exit 1 exit 1
fi fi
# Set up error handler
trap 'error $BASH_SOURCE $FUNCNAME $LINENO $? $BASH_COMMAND' ERR
# ---------------------------------------------------------- # # ---------------------------------------------------------- #
# * Do backups # # * Do backups #
# ---------------------------------------------------------- # # ---------------------------------------------------------- #
log -V "Backup STARTED" log -V "Backup started"
# Check PID file # Check PID file
if [ -e "$pid_file" ]; then if [ -e "$pid_file" ]; then
@ -275,7 +282,7 @@ for script in "${__args[@]}"; do
done done
echo -e "\nBackup [Done]" echo -e "\nBackup [Done]"
log -V "Backup FINISHED" log -V "Backup finished successsfully"
# Remove PID file # Remove PID file
rm "$pid_file" rm "$pid_file"

View File

@ -66,22 +66,33 @@ log() {
done done
} }
handle_error() { error() {
# Handle errors # Handle errors
# #
# Usage: handle_error ERROR_MESSAGE # Usage: error SCRIPTNAME FUNCNAME LINENO EXIT_CODE COMMAND
# Display amd log message local script lastline funcname lasterr msg
log -p "$*" >&2 script="$1"
log -p "Check $log_file log for details." >&2 funcname="$2"
lastline="$3"
lasterr="$4"
shift 4
# Display and log message
msg="ERROR in $script:$lastline: function '$funcname': \
command '$*' failed with exit code $lasterr"
log -p "\e[31m$msg\nCheck $log_file log for details.\e[0m" >&2
# Run user defined error handler function if set # Run user defined error handler function if set
if is_function_set on_error; then if is_function_set on_error; then
echo -e "Run \e[1mon_error()\e[0m" | log -p echo -e "Run \e[1mon_error()\e[0m" | log -p
on_error "$*" on_error "$msg"
fi fi
log -p "Backup ERROR: Exiting with previous errors" >&2; exit 1 log -p Exiting with previous errors. >&2
log -V Backup finished with errors.
exit 1
} }
is_installed() { is_installed() {

View File

@ -63,17 +63,10 @@ src_mysqldump() {
log "Run command: $*" log "Run command: $*"
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if "$@" 2>> "$log_file" > "$sqldump"; then "$@" > "$sqldump" |& log
# Compress file sqldump="$(compress_file "$sqldump")" # Compress file
sqldump="$(compress_file "$sqldump")" backups+=("$sqldump") # Append path to 'backups' array
# Append path to 'backups' array log "Dump saved as: $sqldump"
backups+=("$sqldump")
log "Dump saved as: $sqldump"
else
remove_if_empty "$sqldump"
handle_error \
"Error: Something went wrong when executing command:\n\t$*"
fi
unset MYSQL_PWD unset MYSQL_PWD
} }

View File

@ -64,17 +64,10 @@ src_pg_dump() {
log "Run command: $*" log "Run command: $*"
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if "$@" 2>> "$log_file" > "$sqldump"; then "$@" > "$sqldump" |& log
# Compress dump sqldump="$(compress_file "$sqldump")" # Compress file
sqldump="$(compress_file "$sqldump")" backups+=("$sqldump")
# Append path to 'backups' array log "Dump file: $sqldump"
backups+=("$sqldump")
log "Dump file: $sqldump"
else
remove_if_empty "$sqldump"
handle_error \
"Error: Something went wrong when executing command:\n\t$*"
fi
unset PGPASSWORD unset PGPASSWORD
} }

View File

@ -86,12 +86,7 @@ src_tar() {
log "Run command: $*" log "Run command: $*"
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if "$@" 2>> "$log_file"; then "$@" 2>> "$log_file"
# Append path to 'backups' array # Append path to 'backups' array
backups+=("$archive") backups+=("$archive")
else
remove_if_empty "$archive"
handle_error \
"Error: Something went wrong when executing command:\n\t$*"
fi
} }

View File

@ -59,12 +59,6 @@ tgt_cp() {
set -- cp --archive "$backup" "$dst_path" set -- cp --archive "$backup" "$dst_path"
log "Run command: $*" log "Run command: $*"
"$@" |& log
if "$@" 2>> "$log_file"; then
: # Success
else
handle_error \
"Error: Something went wrong when executing command:\n\t$*"
fi
done done
} }

View File

@ -70,10 +70,6 @@ tgt_s3cmd() {
# Upload backups # Upload backups
# shellcheck disable=SC2154 # shellcheck disable=SC2154
if "$@" 2>> "$log_file"; then #"$@" 2>> "$log_file"
: # Success "$@" |& log
else
handle_error \
"Error: Something went wrong when executing command:\n\t$*"
fi
} }

View File

@ -82,6 +82,7 @@ validate_targets() {
__main_target="${file_targets[0]}" __main_target="${file_targets[0]}"
# Fail if __main_target's path is not a directory # Fail if __main_target's path is not a directory
parse_uri "$__main_target" parse_uri "$__main_target"
# shellcheck disable=SC2154
__main_target_path="$path" __main_target_path="$path"
# Make dirs if `make_target_dir` is set # Make dirs if `make_target_dir` is set