Memperbaiki ide @Fred sedikit lagi, kita dapat membangun perpustakaan logging kecil dengan cara ini:
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 ==="; }
Katakanlah sumber di atas ada dalam file pustaka bernama logging_lib.sh, kita dapat menggunakannya dalam skrip shell biasa dengan cara ini:
#!/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!"
Akan menghasilkan keluaran ini:
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
Seperti yang bisa kita lihat, log_verbose
tidak menghasilkan output apa pun karena level log berada di DEBUG, satu level di bawah VERBOSE. Namun, log_debug_file date.out
memang menghasilkan output dan begitu pula log_execute INFO
, karena level log disetel ke DEBUG, yaitu>=INFO.
Dengan menggunakan ini sebagai basis, kita juga dapat menulis pembungkus perintah jika kita memerlukan penyetelan yang lebih baik lagi:
git_wrapper() {
# run git command and print the output based on log level
}
Dengan ini, skrip dapat ditingkatkan untuk mengambil argumen --log-level level
yang dapat menentukan verbositas log yang harus dijalankannya.
Berikut adalah implementasi lengkap logging untuk Bash, kaya dengan banyak logger:
https://github.com/codeforester/base/blob/master/lib/stdlib.sh
Jika ada yang ingin tahu mengapa beberapa variabel diberi nama dengan garis bawah di depan kode di atas, lihat postingan ini:
- Kapitalisasi variabel skrip Bash dan shell yang benar
Anda sudah memiliki ide yang tampaknya paling bersih dalam pertanyaan Anda (fungsi pembungkus), tetapi menurut Anda itu akan berantakan. Saya sarankan Anda mempertimbangkan kembali. Itu bisa terlihat seperti berikut (belum tentu merupakan solusi lengkap, hanya untuk memberi Anda ide dasar):
#!/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
Anda dapat mengatur pengalihan apa pun yang diperlukan (dengan deskriptor file jika Anda mau) untuk ditangani dalam fungsi pembungkus, sehingga skrip lainnya tetap dapat dibaca dan bebas dari pengalihan dan kondisi bergantung pada tingkat logging yang dipilih.
Solusi 1.Pertimbangkan menggunakan deskriptor file tambahan.Arahkan ulang deskriptor file yang diperlukan ke STDOUT atau /dev/null tergantung pada verbositas yang dipilih.Arahkan output setiap pernyataan dalam skrip Anda ke deskriptor file yang sesuai dengan kepentingannya.Lihat https:// unix.stackexchange.com/a/218355 .