.png)
Em um script bash eu tenho uma log()
função que é usada em vários lugares, bem como uma logs()
função que desvia muita linha para log()
. Quando executo partes do script com set -x
, obviamente todos os comandos dentro de logs()
e log()
também são rastreados.
Eu gostaria de definir logs()
e log()
de forma que pelo menos seu conteúdo, na melhor das hipóteses até mesmo sua chamada, seja suprimida da set -x
saída.
Responder1
Você não pode alterar como a função é chamada de dentro da função, mas pode definir a função para invocar um subshell que desativa imediatamente o rastreamento; observe os parênteses ao redor do corpo em vez dos colchetes típicos:
log() (
set +x
# rest of log()
)
A invocação log()
gera apenas a própria chamada (do set -x
código existente) e a set +x
chamada, e não o restante dos comandos subsequentes na função. A configuração existente set -x
é restaurada assim que a função é encerrada.
Responder2
Um hack rápido e sujo que deve funcionar em todos os shells é (temporariamente) tornar seu log
script externo em vez de uma função.
No bash você também pode usar a combinação trap '...' DEBUG
and shopt -s extdebug
, que é muito mais versátil que set -x
. Exemplo:
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"
}
(Claro, você pode dispensar o formato estranho + recuo e torná-lo completamente set-x
semelhante a -; você também pode redirecioná-lo para outro arquivo em vez de misturá-lo com o stderr dos comandos.)
Então:
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
vai resultar em:
(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
Responder3
Para suprimir a saída do xtrace, basta usar set -x
. Para ligá-lo novamente, use set -x
. Para detectar se está ativado, use shopt -q -o xtrace
. por exemplo
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
}
Ainda há alguma 'conversa', mas é o melhor que posso fazer. Para suprimir a visualização das chamadas para log() você pode cercar cada chamada para log() com um código semelhante em vez de dentro da função.