.png)
En un script bash tengo una log()
función que se usa en varios lugares, así como una logs()
función que desvía muchas líneas a log()
. Cuando ejecuto partes del script con set -x
, obviamente todos los comandos dentro de logs()
y log()
también se rastrean.
Me gustaría definir logs()
y log()
de tal manera que al menos su contenido, en el mejor de los casos incluso su llamada, se suprima de set -x
la salida.
Respuesta1
No puede cambiar cómo se invoca la función desde dentro de la función, pero puede definir la función para que invoque una subcapa que luego desactive inmediatamente el seguimiento; observe el paréntesis que rodea el cuerpo en lugar de las típicas llaves:
log() (
set +x
# rest of log()
)
Luego , la invocación log()
genera solo la llamada en sí (a partir del set -x
código existente) y la set +x
llamada, no el resto de los comandos posteriores en la función. La configuración existente set -x
se restaura una vez que sale la función.
Respuesta2
Un truco rápido y sucio que debería funcionar en todos los shells es convertir (temporalmente) log
un script externo en lugar de una función.
En bash también puedes usar una combinación trap '...' DEBUG
y shopt -s extdebug
, que es mucho más versátil que set -x
. Ejemplo:
debug() {
local f=${FUNCNAME[1]} d=${#FUNCNAME[@]} c=$BASH_COMMAND
if [ "$NOTRACE" ]; then
case $debug_skip in ''|$d) debug_skip=;; *) return;; esac
eval "case \$c in $NOTRACE) debug_skip=\$d; return; esac"
fi
# before the 1st command in a function XXX
case $c in $f|"$f "*) return;; esac
printf >&2 "%*s(%s) %s\n" $((d * 2 - 4)) "" "$f" "$c"
}
(Por supuesto, puede prescindir del formato extraño + sangría y hacerlo completamente set-x
similar; también puede redirigirlo a otro archivo en lugar de mezclarlo con los comandos stderr from).
Entonces:
NOTRACE='"log "*'
shopt -s extdebug
trap debug DEBUG
log(){ log1 "$@"; }; log1(){ log2 "$@"; }
log2(){ log3 "$@"; }; log3(){ echo "$@"; }
foo(){ foo1 "$@"; }; foo1(){ foo2 "$@"; }
foo2(){ foo3 "$@"; }; foo3(){ echo "$@"; }
bar(){ case $# in 0) ;; *) echo "$1"; shift; bar "$@";; esac; }
foo 1 2 3
log 7 8 9
bar 1 2 3 4
resultará en:
(main) foo 1 2 3
(foo) foo1 "$@"
(foo1) foo2 "$@"
(foo2) foo3 "$@"
(foo3) echo "$@"
1 2 3
7 8 9
(main) bar 1 2 3 4
(bar) case $# in
(bar) echo "$1"
1
(bar) shift
(bar) case $# in
(bar) echo "$1"
2
(bar) shift
(bar) case $# in
(bar) echo "$1"
3
(bar) shift
(bar) case $# in
(bar) echo "$1"
4
(bar) shift
(bar) case $# in
Respuesta3
Para suprimir la salida de xtrace, simplemente use set -x
. Para volver a encenderlo, utilice set -x
. Para detectar si está encendido, use shopt -q -o xtrace
. p.ej
log() {
if shopt -q -o xtrace; then TRACE_IS_ON=yes; else TRACE_IS_ON=no; fi
set +x # turn xtrace off
...
[[ "$TRACE_IS_ON" == "yes" ]] && set +x
}
Todavía hay algunas "charlas", pero eso es lo mejor que puedo hacer. Para evitar ver las llamadas a log(), puede rodear cada llamada a log() con un código similar en lugar de hacerlo dentro de la función.