Quand j'écris des scripts bash, j'obtiens généralement le mode commenté (simplifié):
_V=0
while getopts "v" OPTION
do
case $OPTION in
v) _V=1
;;
esac
done
et puis chaque fois que je veux une "sortie prolixe" je tape ceci:
[ $_V -eq 1 ] && echo "verbose mode on" || echo "verbose mode off"
ou par exemple ceci:
[ $_V -eq 1 ] && command -v || command
Y a-t-il un moyen de le faire plus élégant? Je pensais définir une fonction nommée "verbose" et la taper à la place de [ $_V -eq 1 ]
, mais ce ne serait qu'une infime amélioration.
Je suis sûr qu'il y a une manière plus commune de le faire…
Comme vous l'avez remarqué, vous pouvez définir des fonctions log
telles que log
, log_debug
, log_error
, etc.
function log () {
if [[ $_V -eq 1 ]]; then
echo "$@"
fi
}
Cela peut aider à augmenter la lisibilité de votre code principal et à masquer la logique show\nonshow dans la fonction de journalisation.
log "some text"
Si _V
(variable globale) est égal à 1
"du texte" sera imprimé, sinon ce ne sera pas le cas.
Après avoir lu tous les autres posts, je suis venu avec ce
# set verbose level to info
__VERBOSE=6
declare -A LOG_LEVELS
# https://en.wikipedia.org/wiki/Syslog#Severity_level
LOG_LEVELS=([0]="emerg" [1]="alert" [2]="crit" [3]="err" [4]="warning" [5]="notice" [6]="info" [7]="debug")
function .log () {
local LEVEL=${1}
shift
if [ ${__VERBOSE} -ge ${LEVEL} ]; then
echo "[${LOG_LEVELS[$LEVEL]}]" "$@"
fi
}
Ensuite, vous pouvez simplement l'utiliser comme ça
# verbose error
.log 3 "Something is wrong here"
Qui va sortir
[error] Something is wrong here
#!/bin/bash
# A flexible verbosity redirection function
# John C. Petrucci (http://johncpetrucci.com)
# 2013-10-19
# Allows your script to accept varying levels of verbosity flags and give appropriate feedback via file descriptors.
# Example usage: ./this [-v[v[v]]]
verbosity=2 #Start counting at 2 so that any increase to this will result in a minimum of file descriptor 3. You should leave this alone.
maxverbosity=5 #The highest verbosity we use / allow to be displayed. Feel free to adjust.
while getopts ":v" opt; do
case $opt in
v) (( verbosity=verbosity+1 ))
;;
esac
done
printf "%s %d\n" "Verbosity level set to:" "$verbosity"
for v in $(seq 3 $verbosity) #Start counting from 3 since 1 and 2 are standards (stdout/stderr).
do
(( "$v" <= "$maxverbosity" )) && echo This would display $v
(( "$v" <= "$maxverbosity" )) && eval exec "$v>&2" #Don't change anything higher than the maximum verbosity allowed.
done
for v in $(seq $(( verbosity+1 )) $maxverbosity ) #From the verbosity level one higher than requested, through the maximum;
do
(( "$v" > "2" )) && echo This would not display $v
(( "$v" > "2" )) && eval exec "$v>/dev/null" #Redirect these to bitbucket, provided that they don't match stdout and stderr.
done
# Some confirmations:
printf "%s\n" "This message is seen at verbosity level 3 and above." >&3
printf "%s\n" "This message is seen at verbosity level 4 and above." >&4
printf "%s\n" "This message is seen at verbosity level 5 and above." >&5
Un premier essai avec un système plus flexible avec des niveaux de verbosité (Bash 4):
# CONFIG SECTION
# verbosity level definitions
config[verb_levels]='debug info status warning error critical fatal'
# verbosity levels that are to be user-selectable (0-this value)
config[verb_override]=3
# user-selected verbosity levels (0=none, 1=warnings, 2=warnings+info, 3=warning+info+debug)
config[verbosity]=2
# FUNCTION DEFINITIONS SECTION
_messages() {
# shortcut functions for messages
# non overridable levels exit with errlevel
# safe eval, it only uses two (namespaced) values, and a few builtins
local verbosity macro level=0
for verbosity in ${config[verb_levels]}; do
IFS="" read -rd'' macro <<MACRO
_$verbosity() {
$( (( $level <= ${config[verb_override]} )) && echo "(( \${config[verbosity]} + $level > ${config[verb_override]} )) &&" ) echo "${verbosity}: \$@";
$( (( $level > ${config[verb_override]} )) && echo "exit $(( level - ${config[verb_override]} ));" )
}
MACRO
eval "$macro"
(( level++ ))
done
}
# INITIALIZATION SECTION
_messages
Après l’initialisation, n’importe où dans votre code, vous pouvez utiliser des éléments tels que:
! (( $# )) && _error "parameter expected"
[[ -f somefile ]] && _warning "file $somefile already exists"
_info "some info"
_status "running command"
if (( ${config[verbosity]} <= 1 )); then
command
else
command -v
fi
# explicitly changing verbosity at run time
old_verbosity=${config[verbosity]}
config[verbosity]=1
etc.
Je suis également venu avec cette fonction pour faire un rapide ifelse:
function verbose () {
[[ $_V -eq 1 ]] && return 0 || return 1
}
Ceci exécute une commande si $ _V a la valeur 1. Utilisez-le comme ceci:
verbose && command #command will be executed if $_V == 1
ou
verbose && command -v || command # execute 'command -v' if $_V==1, else execute 'command'
Si vous voulez éviter de faire une déclaration "if" à chaque fois que vous voulez enregistrer quelque chose, vous pouvez essayer cette approche (c'est comment je le fais).
L'idée est qu'au lieu d'appeler log
, vous appelez plutôt $echoLog
. Donc, si vous êtes en mode verbeux, $echoLog
sera simplement echo
, mais en mode non-verbose, il s’agira d’une fonction qui n’affiche rien et ignore les arguments.
Voici du code que vous pouvez copier.
# Use `$echoLog` everywhere you print verbose logging messages to console
# By default, it is disabled and will be enabled with the `-v` or `--verbose` flags
declare echoLog='silentEcho'
function silentEcho() {
:
}
# Somewhere else in your script's setup, do something like this
while [[ $# > 0 ]]; do
case "$1" in
-v|--verbose) echoLog='echo'; ;;
esac
shift;
done
Maintenant, vous pouvez simplement supprimer des lignes comme $echoLog "Doing something verbose log worthy"
où vous voulez.
verbose=false
while getopts "v" OPTION
do
case $OPTION in
v) verbose=true
;;
esac
done
Ensuite
$verbose && echo "Verbose mode on" || echo "Verbose mode off"
Ceci exécutera /bin/true
ou /bin/false
, renvoyant 0 ou 1 respectivement.
Pour éviter d'utiliser plusieurs instructions if ou d'utiliser une variable pour conserver un nom de fonction, pourquoi ne pas déclarer différentes fonctions en fonction de la verbosité!
Cela fonctionne pour TOUS les dérivés bourne Shell, pas seulement bash!
#verbose=verbose_true # uncomment to make script verbose
if [ "$verbose" ]; then
log() { echo "$@"; }
else
log() { :; }
fi
log This Script is Verbose
NOTE: l'utilisation de "verbose = verbose_true" rend le traçage de script beaucoup plus agréable Mais vous pouvez le créer si vous le souhaitez.