Abychom myšlenku @Freda ještě trochu vylepšili, mohli bychom vytvořit malou protokolovací knihovnu tímto způsobem:
declare -A _log_levels=([FATAL]=0 [ERROR]=1 [WARN]=2 [INFO]=3 [DEBUG]=4 [VERBOSE]=5)
declare -i _log_level=3
set_log_level() {
level="${1:-INFO}"
_log_level="${_log_levels[$level]}"
}
log_execute() {
level=${1:-INFO}
if (( $1 >= ${_log_levels[$level]} )); then
"${@:2}" >/dev/null
else
"${@:2}"
fi
}
log_fatal() { (( _log_level >= ${_log_levels[FATAL]} )) && echo "$(date) FATAL $*"; }
log_error() { (( _log_level >= ${_log_levels[ERROR]} )) && echo "$(date) ERROR $*"; }
log_warning() { (( _log_level >= ${_log_levels[WARNING]} )) && echo "$(date) WARNING $*"; }
log_info() { (( _log_level >= ${_log_levels[INFO]} )) && echo "$(date) INFO $*"; }
log_debug() { (( _log_level >= ${_log_levels[DEBUG]} )) && echo "$(date) DEBUG $*"; }
log_verbose() { (( _log_level >= ${_log_levels[VERBOSE]} )) && echo "$(date) VERBOSE $*"; }
# functions for logging command output
log_debug_file() { (( _log_level >= ${_log_levels[DEBUG]} )) && [[ -f $1 ]] && echo "=== command output start ===" && cat "$1" && echo "=== command output end ==="; }
log_verbose_file() { (( _log_level >= ${_log_levels[VERBOSE]} )) && [[ -f $1 ]] && echo "=== command output start ===" && cat "$1" && echo "=== command output end ==="; }
Řekněme, že výše uvedený zdroj je v souboru knihovny s názvem logging_lib.sh, mohli bychom jej použít v běžném skriptu shellu takto:
#!/bin/bash
source /path/to/lib/logging_lib.sh
set_log_level DEBUG
log_info "Starting the script..."
# method 1 of controlling a command's output based on log level
log_execute INFO date
# method 2 of controlling the output based on log level
date &> date.out
log_debug_file date.out
log_debug "This is a debug statement"
...
log_error "This is an error"
...
log_warning "This is a warning"
...
log_fatal "This is a fatal error"
...
log_verbose "This is a verbose log!"
Výsledkem bude tento výstup:
Fri Feb 24 06:48:18 UTC 2017 INFO Starting the script...
Fri Feb 24 06:48:18 UTC 2017
=== command output start ===
Fri Feb 24 06:48:18 UTC 2017
=== command output end ===
Fri Feb 24 06:48:18 UTC 2017 DEBUG This is a debug statement
Fri Feb 24 06:48:18 UTC 2017 ERROR This is an error
Fri Feb 24 06:48:18 UTC 2017 ERROR This is a warning
Fri Feb 24 06:48:18 UTC 2017 FATAL This is a fatal error
Jak vidíme, log_verbose
neprodukoval žádný výstup, protože úroveň protokolu je na DEBUG, o jednu úroveň pod VERBOSE. Nicméně log_debug_file date.out
vytvořil výstup a stejně tak log_execute INFO
, protože úroveň protokolu je nastavena na DEBUG, což je>=INFO.
Když to použijeme jako základ, mohli bychom také napsat obaly příkazů, pokud potřebujeme ještě jemnější doladění:
git_wrapper() {
# run git command and print the output based on log level
}
S těmi na místě by mohl být skript vylepšen tak, aby přijal argument --log-level level
který může určit podrobnost protokolu, se kterou by měl běžet.
Zde je kompletní implementace protokolování pro Bash, bohatá na více protokolů:
https://github.com/codeforester/base/blob/master/lib/stdlib.sh
Pokud někoho zajímá, proč jsou některé proměnné ve výše uvedeném kódu pojmenovány s podtržítkem na začátku, podívejte se na tento příspěvek:
- Správná velká písmena proměnných skriptu Bash a shell
Ve své otázce již máte to, co se zdá být nejčistší (funkce wrapper), ale zdá se, že si myslíte, že by to bylo chaotické. Navrhoval bych, abyste to přehodnotili. Mohlo by to vypadat následovně (ne nutně plnohodnotné řešení, jen pro základní představu):
#!/bin/bash
# Argument 1 : Logging level for that command
# Arguments 2... : Command to execute
# Output suppressed if command level >= current logging level
log()
{
if
(($1 >= logging_level))
then
"${@:2}" >/dev/null 2>&1
else
"${@:2}"
fi
}
logging_level=2
log 1 command1 and its args
log 2 command2 and its args
log 3 command4 and its args
Můžete zařídit, aby jakékoli požadované přesměrování (pokud chcete s deskriptory souborů) bylo zpracováno ve funkci wrapper, takže zbytek skriptu zůstane čitelný a bez přesměrování a podmínek v závislosti na zvolené úrovni protokolování.
Řešení 1. Zvažte použití dalších deskriptorů souborů. Přesměrujte požadované deskriptory souborů na STDOUT nebo /dev/null v závislosti na zvolené upovídanosti. Přesměrujte výstup každého příkazu ve vašem skriptu na deskriptor souboru odpovídající jeho důležitosti. Podívejte se na https:// unix.stackexchange.com/a/218355 .