Bash
定義未出現在 xtrace 中的 bash 函式(set -x)
在 bash 腳本中,我有一個
log()
在多個地方使用的函式,以及一個logs()
將大量行轉移到log()
. 當我使用 執行部分腳本時set -x
,顯然logs()
和中的所有命令log()
也會被跟踪。我想定義
logs()
,log()
至少他們的內容,充其量甚至他們的呼叫都被從set -x
輸出中抑制。
應該適用於所有 shell 的快速而骯髒的 hack 是(暫時)使您
log
的外部腳本而不是函式。在 bash 中,您還可以使用 a
trap '...' DEBUG
andshopt -s extdebug
組合,它比set -x
. 例子: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" }
(當然,您可以放棄奇怪的格式 + 縮進並使其完全
set-x
類似;您還可以將其重定向到另一個文件,而不是與命令中的 stderr 混合。)然後:
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
將導致:
(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
您無法更改從函式內部呼叫函式的方式,但您可以定義函式以呼叫子shell,然後立即關閉跟踪;注意主體周圍的括號而不是典型的大括號:
log() ( set +x # rest of log() )
然後呼叫
log()
僅生成呼叫本身(來自現有set -x
程式碼)和set +x
呼叫,而不是函式中的其餘後續命令。一旦函式退出,現有set -x
設置就會恢復。