#!/usr/bin/env bash # common.sh - common functions. # Copyright (c) 2022 ge # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . log() { # Logger. Write message to __log_file. # # Usage: log [-p] MESSAGE # # Can read from STDIN. Removes ANSI escape codes from log message. # Echo message to STDOUT with '-p' option. local message local print # Read message from STDIN if args not passed. [[ ! -t 0 ]] || [[ "$#" == 0 ]] && message="$(cat <&0)" # Set log date format [ "$log_date_fmt" ] || log_date_fmt="$__log_date_fmt" while (( "$#" )); do case "$1" in -p) print=1; shift;; -) message="$(cat <&0)"; shift "$#";; *) message="$*"; shift "$#";; esac done [[ "$print" == 1 ]] && echo -e "$message" while read -r line; do if [[ "$line" ]]; then printf '[%s] %s\n' "$(date +"$log_date_fmt")" "$line" >> "$__log_file" fi done <<< "$(sed -r 's/\x1B\[(([0-9]+)(;[0-9]+)*)?[m,K,H,f,J]//g' <<< "$message")" } err() { # Handle errors. Print errors to STDERR, log, process # and exit from script. # # Usage: err [-eao] MESSAGE local message local errexit local errappend local onerr [[ ! -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 '-{} ')" set -- "$@" $args;; *) 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 # Exit if [ "$errexit" ]; then # Count errors for backup recap __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 if eval "$@" 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() { # Check if the program is installed. # See good answer: https://stackoverflow.com/a/677212 # # Usage: is_installed COMMAND if ! command -v "$1" >/dev/null 2>&1; then echo "Error: Command $1 not found." \ "Please install $1 or check your PATH if it's actually installed." >&2 exit 1 fi } is_function_set() { # Test function is set or not. Return exit code. # Useful with 'if' statement. # # Usage: is_function_set FUNCTION declare -F -- "$1" > /dev/null return "$?" } set_compression() { # Set compr_util and file_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';; *) file_ext=''; compr_util='';; # No compression esac }