feat: Remove try; Add err, gen_backup_name, compress_file; Update log
This commit is contained in:
		@@ -19,119 +19,69 @@
 | 
				
			|||||||
log() {
 | 
					log() {
 | 
				
			||||||
    # Logger. Write message to __log_file.
 | 
					    # 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.
 | 
					    # 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 message
 | 
				
			||||||
    local print
 | 
					    local print
 | 
				
			||||||
 | 
					    local ignore_verbose
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Read message from STDIN if args not passed.
 | 
					    # Read message from STDIN if args not passed.
 | 
				
			||||||
    [[ ! -t 0 ]] || [[ "$#" == 0 ]] && message="$(cat <&0)"
 | 
					    [[ ! -t 0 ]] || [[ "$#" == 0 ]] && message="$(cat <&0)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Set log date format
 | 
					    # 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
 | 
					    while (( "$#" )); do
 | 
				
			||||||
        case "$1" in
 | 
					        case "$1" in
 | 
				
			||||||
            -p) print=1; shift;;
 | 
					            -p) print=1; shift;;
 | 
				
			||||||
 | 
					            -V) ignore_verbose=1; shift;;
 | 
				
			||||||
            -)  message="$(cat <&0)"; shift "$#";;
 | 
					            -)  message="$(cat <&0)"; shift "$#";;
 | 
				
			||||||
            *)  message="$*"; shift "$#";;
 | 
					            *)  message="$*"; shift "$#";;
 | 
				
			||||||
        esac
 | 
					        esac
 | 
				
			||||||
    done
 | 
					    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
 | 
					    while read -r line; do
 | 
				
			||||||
        if [ -n "$line" ]; then
 | 
					        if [ -n "$line" ]; then
 | 
				
			||||||
            # shellcheck disable=SC2154
 | 
					            # shellcheck disable=SC2154
 | 
				
			||||||
            printf '[%s] %s\n' "$(date +"$log_date_fmt")" "$line" \
 | 
					            printf '[%s] %s\n' \
 | 
				
			||||||
                >> "$__log_file"
 | 
					                "$(date +"$log_date_format")" "$line" >> "$__log_file"
 | 
				
			||||||
        fi
 | 
					        fi
 | 
				
			||||||
    done <<< "$(<<< "$message" \
 | 
					    done
 | 
				
			||||||
        sed -r 's/\x1B\[(([0-9]+)(;[0-9]+)*)?[m,K,H,f,J]//g')"
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err() {
 | 
					handle_error() {
 | 
				
			||||||
    # Handle errors. Print errors to STDERR, log, process
 | 
					    # Handle errors
 | 
				
			||||||
    # and exit from script.
 | 
					 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # Usage: err [-eao] MESSAGE
 | 
					    # Usage: handle_error ERROR_MESSAGE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    local message
 | 
					    # Display amd log message
 | 
				
			||||||
    local errexit
 | 
					    log -p "$*" >&2
 | 
				
			||||||
    local errappend
 | 
					    log -p "Check $__log_file log for details." >&2
 | 
				
			||||||
    local onerr
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [[ ! -t 0 ]] || [[ "$#" == 0 ]] && message="$(cat <&0)"
 | 
					    # Run user defined error handler function if set
 | 
				
			||||||
 | 
					    if is_function_set on_error; then
 | 
				
			||||||
    # Split combined short options, e.g. '-abc' to '-a' '-b' '-c'
 | 
					        echo -e "Run \e[1mon_error()\e[0m" | log -p
 | 
				
			||||||
    for args in "$@"; do
 | 
					        on_error "$*"
 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Exit
 | 
					    log -p "Backup ERROR: Exiting with previous errors" >&2; exit 1
 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is_installed() {
 | 
					is_installed() {
 | 
				
			||||||
    # Check if the program is installed.
 | 
					    # Test is the program installed.
 | 
				
			||||||
    # See good answer: https://stackoverflow.com/a/677212
 | 
					    # See good answer: https://stackoverflow.com/a/677212
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # Usage: is_installed COMMAND
 | 
					    # Usage: is_installed COMMAND
 | 
				
			||||||
@@ -145,7 +95,7 @@ is_installed() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
is_function_set() {
 | 
					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.
 | 
					    # Useful with 'if' statement.
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # Usage: is_function_set FUNCTION
 | 
					    # Usage: is_function_set FUNCTION
 | 
				
			||||||
@@ -154,33 +104,100 @@ is_function_set() {
 | 
				
			|||||||
    return "$?"
 | 
					    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_compression() {
 | 
				
			||||||
    # Set compr_util and file_ext by name.
 | 
					    # Set `compr_cmd` and `compr_ext` by name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Select compression utility and set filename extension.
 | 
					    # Select compression utility and set filename extension.
 | 
				
			||||||
    # Refference: https://www.gnu.org/software/tar/manual/html_node/gzip.html
 | 
					    # Refference: https://www.gnu.org/software/tar/manual/html_node/gzip.html
 | 
				
			||||||
    case "$1" in
 | 
					    case "$1" in
 | 
				
			||||||
        gzip|gz)    file_ext='.gz';      compr_util='gzip';;
 | 
					        gzip|gz)    compr_ext='.gz';      compr_cmd='gzip';;
 | 
				
			||||||
        tgz)        file_ext='.gz';      compr_util='gzip';;
 | 
					        tgz)        compr_ext='.gz';      compr_cmd='gzip';;
 | 
				
			||||||
        taz)        file_ext='.gz';      compr_util='gzip';;
 | 
					        taz)        compr_ext='.gz';      compr_cmd='gzip';;
 | 
				
			||||||
        compress|Z) file_ext='.Z';       compr_util='compress';;
 | 
					        compress|Z) compr_ext='.Z';       compr_cmd='compress';;
 | 
				
			||||||
        taZ)        file_ext='.Z';       compr_util='compress';;
 | 
					        taZ)        compr_ext='.Z';       compr_cmd='compress';;
 | 
				
			||||||
        bzip2|bz2)  file_ext='.bz2';     compr_util='bzip2';;
 | 
					        bzip2|bz2)  compr_ext='.bz2';     compr_cmd='bzip2';;
 | 
				
			||||||
        tz2)        file_ext='.bz2';     compr_util='bzip2';;
 | 
					        tz2)        compr_ext='.bz2';     compr_cmd='bzip2';;
 | 
				
			||||||
        tbz2)       file_ext='.bz2';     compr_util='bzip2';;
 | 
					        tbz2)       compr_ext='.bz2';     compr_cmd='bzip2';;
 | 
				
			||||||
        tbz)        file_ext='.bz2';     compr_util='bzip2';;
 | 
					        tbz)        compr_ext='.bz2';     compr_cmd='bzip2';;
 | 
				
			||||||
        lzip|lz)    file_ext='.lz';      compr_util='lzip';;
 | 
					        lzip|lz)    compr_ext='.lz';      compr_cmd='lzip';;
 | 
				
			||||||
        lzma)       file_ext='.lzma';    compr_util='lzma';;
 | 
					        lzma)       compr_ext='.lzma';    compr_cmd='lzma';;
 | 
				
			||||||
        tlz)        file_ext='.lzma';    compr_util='lzma';;
 | 
					        tlz)        compr_ext='.lzma';    compr_cmd='lzma';;
 | 
				
			||||||
        lzop|lzo)   file_ext='.lzop';    compr_util='lzop';;
 | 
					        lzop|lzo)   compr_ext='.lzop';    compr_cmd='lzop';;
 | 
				
			||||||
        xz)         file_ext='.xz';      compr_util='xz';;
 | 
					        xz)         compr_ext='.xz';      compr_cmd='xz';;
 | 
				
			||||||
        zstd|zst)   file_ext='.zst';     compr_util='zstd';;
 | 
					        zstd|zst)   compr_ext='.zst';     compr_cmd='zstd --rm';;
 | 
				
			||||||
        tzst)       file_ext='.zst';     compr_util='zstd';;
 | 
					        tzst)       compr_ext='.zst';     compr_cmd='zstd --rm';;
 | 
				
			||||||
        *)  # No compression
 | 
					        *)  # No compression
 | 
				
			||||||
            # shellcheck disable=SC2034
 | 
					            # shellcheck disable=SC2034
 | 
				
			||||||
            file_ext=''
 | 
					            compr_ext=
 | 
				
			||||||
            # shellcheck disable=SC2034
 | 
					            # shellcheck disable=SC2034
 | 
				
			||||||
            compr_util=''
 | 
					            compr_cmd=
 | 
				
			||||||
            ;;
 | 
					            ;;
 | 
				
			||||||
    esac
 | 
					    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}"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user