From bafb8b729a22a874591aa5518e65998b8bb5c66e Mon Sep 17 00:00:00 2001 From: ge Date: Sun, 21 Aug 2022 04:48:26 +0300 Subject: [PATCH] feat: Remove try; Add err, gen_backup_name, compress_file; Update log --- src/lib/common.sh | 215 +++++++++++++++++++++++++--------------------- 1 file changed, 116 insertions(+), 99 deletions(-) diff --git a/src/lib/common.sh b/src/lib/common.sh index 55497b8..014acfb 100644 --- a/src/lib/common.sh +++ b/src/lib/common.sh @@ -19,119 +19,69 @@ log() { # Logger. Write message to __log_file. # - # Usage: log [-p] MESSAGE + # Usage: log [-pV] MESSAGE # # Can read from STDIN. Removes ANSI escape codes from log message. - # Echo message to STDOUT with '-p' option. + # Options: + # -p echo message to STDOUT too + # -V do not print message to STDOUT in verbose mode local message local print + local ignore_verbose # Read message from STDIN if args not passed. [[ ! -t 0 ]] || [[ "$#" == 0 ]] && message="$(cat <&0)" # Set log date format - log_date_fmt="${log_date_fmt:-%d/%b/%Y:%H:%M:%S %z}" + log_date_format="${log_date_format:-%d/%b/%Y:%H:%M:%S %z}" while (( "$#" )); do case "$1" in -p) print=1; shift;; + -V) ignore_verbose=1; shift;; -) message="$(cat <&0)"; shift "$#";; *) message="$*"; shift "$#";; esac done - [[ "$print" == 1 ]] && echo -e "$message" + if [ -n "$print" ] || [ -n "$__verbose" ]; then + if [ -n "$print" ] || [ -z "$ignore_verbose" ]; then + echo -e "$message" + fi + fi + echo -e "$message" | + sed -r 's/\x1B\[(([0-9]+)(;[0-9]+)*)?[m,K,H,f,J]//g' | while read -r line; do if [ -n "$line" ]; then # shellcheck disable=SC2154 - printf '[%s] %s\n' "$(date +"$log_date_fmt")" "$line" \ - >> "$__log_file" + printf '[%s] %s\n' \ + "$(date +"$log_date_format")" "$line" >> "$__log_file" fi - done <<< "$(<<< "$message" \ - sed -r 's/\x1B\[(([0-9]+)(;[0-9]+)*)?[m,K,H,f,J]//g')" + done } -err() { - # Handle errors. Print errors to STDERR, log, process - # and exit from script. +handle_error() { + # Handle errors # - # Usage: err [-eao] MESSAGE + # Usage: handle_error ERROR_MESSAGE - local message - local errexit - local errappend - local onerr + # Display amd log message + log -p "$*" >&2 + log -p "Check $__log_file log for details." >&2 - [[ ! -t 0 ]] || [[ "$#" == 0 ]] && message="$(cat <&0)" - - # Split combined short options, e.g. '-abc' to '-a' '-b' '-c' - for args in "$@"; do - shift - case "$args" in - -*) - args="$(echo "${args:1}" | grep -o . | - xargs -I {} echo -n '-{} ')" - # shellcheck disable=SC2086 - set -- "$@" $args;; # 'args' must be unquoted! - *) - set -- "$@" "$args";; # save positional arguments - esac - done - - while (( "$#" )); do - case "$1" in - -e) errexit=1; shift;; - -a) errappend=1; shift;; - -o) onerr=1; shift;; - -) message="$(cat <&0)"; shift "$#";; - *) message="$*"; shift "$#";; - esac - done - - log "$message" - echo -e "$message" >&2 - [ "$errappend" ] && errors+=("$message") - - # Run user defined function on_error() - if [ "$onerr" ]; then - if is_function_set on_error; then - echo -e "Run \e[1mon_error()\e[0m" | log -p - on_error - fi + # Run user defined error handler function if set + if is_function_set on_error; then + echo -e "Run \e[1mon_error()\e[0m" | log -p + on_error "$*" fi - # Exit - if [ "$errexit" ]; then - # Count errors for backup recap - # shellcheck disable=SC2154 - __errors_count="$(cat "$__errors_file")" - ((__errors_count++)) || true - echo "$__errors_count" > "$__errors_file" - - log -p "Backup ERROR: Exiting with previous errors" >&2; exit 1 - fi -} - -try() { - # Commands wrapper for error handling - # - # Usage: try COMMAND - - # https://www.shellcheck.net/wiki/SC2294 - if "$@" 2>> "$__log_file"; then - return 0 # Success - else - # Count errors - err -a "Error: Something went wrong when executing command:" - err -a " $*" - err -aeo "Check $__log_file log for details." - fi + log -p "Backup ERROR: Exiting with previous errors" >&2; exit 1 } is_installed() { - # Check if the program is installed. + # Test is the program installed. # See good answer: https://stackoverflow.com/a/677212 # # Usage: is_installed COMMAND @@ -145,7 +95,7 @@ is_installed() { } is_function_set() { - # Test function is set or not. Return exit code. + # Test is function set or not. Return exit code. # Useful with 'if' statement. # # Usage: is_function_set FUNCTION @@ -154,33 +104,100 @@ is_function_set() { return "$?" } +remove_if_empty() { + # Delete empty file + # + # Usage: remove_empty FILE + + if [ -f "$1" ]; then + if [ ! -s "$1" ]; then + log -p "Backup size is 0 bytes. Removing $1" >&2 + rm "$1" + fi + fi +} + set_compression() { - # Set compr_util and file_ext by name. + # Set `compr_cmd` and `compr_ext` by name. # Select compression utility and set filename extension. # Refference: https://www.gnu.org/software/tar/manual/html_node/gzip.html case "$1" in - gzip|gz) file_ext='.gz'; compr_util='gzip';; - tgz) file_ext='.gz'; compr_util='gzip';; - taz) file_ext='.gz'; compr_util='gzip';; - compress|Z) file_ext='.Z'; compr_util='compress';; - taZ) file_ext='.Z'; compr_util='compress';; - bzip2|bz2) file_ext='.bz2'; compr_util='bzip2';; - tz2) file_ext='.bz2'; compr_util='bzip2';; - tbz2) file_ext='.bz2'; compr_util='bzip2';; - tbz) file_ext='.bz2'; compr_util='bzip2';; - lzip|lz) file_ext='.lz'; compr_util='lzip';; - lzma) file_ext='.lzma'; compr_util='lzma';; - tlz) file_ext='.lzma'; compr_util='lzma';; - lzop|lzo) file_ext='.lzop'; compr_util='lzop';; - xz) file_ext='.xz'; compr_util='xz';; - zstd|zst) file_ext='.zst'; compr_util='zstd';; - tzst) file_ext='.zst'; compr_util='zstd';; + gzip|gz) compr_ext='.gz'; compr_cmd='gzip';; + tgz) compr_ext='.gz'; compr_cmd='gzip';; + taz) compr_ext='.gz'; compr_cmd='gzip';; + compress|Z) compr_ext='.Z'; compr_cmd='compress';; + taZ) compr_ext='.Z'; compr_cmd='compress';; + bzip2|bz2) compr_ext='.bz2'; compr_cmd='bzip2';; + tz2) compr_ext='.bz2'; compr_cmd='bzip2';; + tbz2) compr_ext='.bz2'; compr_cmd='bzip2';; + tbz) compr_ext='.bz2'; compr_cmd='bzip2';; + lzip|lz) compr_ext='.lz'; compr_cmd='lzip';; + lzma) compr_ext='.lzma'; compr_cmd='lzma';; + tlz) compr_ext='.lzma'; compr_cmd='lzma';; + lzop|lzo) compr_ext='.lzop'; compr_cmd='lzop';; + xz) compr_ext='.xz'; compr_cmd='xz';; + zstd|zst) compr_ext='.zst'; compr_cmd='zstd --rm';; + tzst) compr_ext='.zst'; compr_cmd='zstd --rm';; *) # No compression # shellcheck disable=SC2034 - file_ext='' + compr_ext= # shellcheck disable=SC2034 - compr_util='' + compr_cmd= ;; esac + + [ -z "$compr_cmd" ] && return # Exit from function if no compression set + + is_installed "${compr_cmd%% *}" +} + +compress_file() { + # Compress and echo compressed file name. Remove uncompressed file. + # + # Usage: compress_file FILE + + local compressed + + # Select compression utility and set filename extension. + if [ -n "$compression" ]; then + set_compression "$compression" + else + compr_cmd= + compr_ext= + fi + + # Compress file + if [ -n "$compr_cmd" ]; then + log -V "Compressing file $1 by ${compr_cmd%% *} ..." + $compr_cmd "$1" 2>> "$__log_file" + compressed="${1}${compr_ext}" + fi + + if [ -f "$compressed" ]; then + if [ -f "$1" ]; then + log "Remove uncompressed file $1" + rm -- "$1" + fi + fi + + echo "$compressed" +} + +gen_backup_name() { + # Generate backup file name. Write resulting string to STDOUT. + # + # Usage: gen_backup_name NAME_EXT + + local name + local name_ext + + name_prefix="${name_prefix:-${backup_script##*/}_}" + # shellcheck disable=SC2154 + name="$(basename "$path")" # `path` is variable parsed from URI + name_ext="$1" + name_date_format="${name_date_format:-_%Y.%m.%d}" + name_suffix="${name_suffix:--%H%M}" + + date +"${name_prefix}${name}${name_date_format}${name_suffix}${name_ext}" }