@Fred のアイデアをもう少し改良すると、この方法で小さなロギング ライブラリを構築できます。
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 ==="; }
上記のソースが logging_lib.sh という名前のライブラリ ファイルにあるとしましょう。これを通常のシェル スクリプトで次のように使用できます。
#!/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!"
この出力は次のようになります:
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
ご覧のとおり、log_verbose
ログ レベルが VERBOSE の 1 レベル下の DEBUG であるため、出力は生成されませんでした。ただし、log_debug_file date.out
出力を生成し、log_execute INFO
も生成しました 、ログ レベルが DEBUG に設定されているため、>=INFO.
これをベースとして使用して、さらに微調整が必要な場合は、コマンド ラッパーを作成することもできます。
git_wrapper() {
# run git command and print the output based on log level
}
これらを配置すると、引数 --log-level level
を取るようにスクリプトを拡張できます。 実行すべきログの詳細度を決定できます。
以下は、複数のロガーを備えた豊富な Bash のロギングの完全な実装です:
https://github.com/codeforester/base/blob/master/lib/stdlib.sh
上記のコードで一部の変数の名前が先頭にアンダースコアが付いている理由に興味がある人は、次の投稿を参照してください:
- Bash とシェル スクリプトの変数の大文字と小文字を正しくする
あなたの質問で最もクリーンなアイデア(ラッパー関数)と思われるものはすでにありますが、それは面倒だと思うようです。再考することをお勧めします。次のようになります (必ずしも完全な解決策ではありません。基本的な考え方を示すためです):
#!/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
必要なリダイレクト (必要に応じてファイル記述子を使用) をラッパー関数で処理するように調整できます。これにより、スクリプトの残りの部分は引き続き読み取り可能であり、選択したログ レベルに応じてリダイレクトや条件から解放されます。
解決策 1.追加のファイル記述子の使用を検討します。選択した詳細度に応じて、必要なファイル記述子を STDOUT または /dev/null にリダイレクトします。スクリプト内のすべてのステートメントの出力を、その重要性に対応するファイル記述子にリダイレクトします。https:// をご覧ください。 unix.stackexchange.com/a/218355 .