一時的にbashオプションの設定を解除する-x

一時的にbashオプションの設定を解除する-x

set -x私は何が起こっているのかを示すためにスクリプトでこれを使用するのが好きです。特に、スクリプトがCI / CDパイプラインで実行され、実際には後でいくつかのエラーをデバッグする必要があるかもしれません。

これに対する面倒なのは、一部のテキスト(ステータスメッセージなど)をユーザーに再エコーしたい場合は、"I'm starting to do $X"そのメッセージが2回出力されることです。一度はechoコマンド自体をエコーし​​、一度はechoそのコマンドの出力に出力します。

これをより良くするための良い方法はありますか? 1つの解決策は次のとおりです。

set -x

... bunch of normal commands that get echoed

(
  # Temporarily don't echo, so we don't double-echo
  set +x
  echo "Here is my status message"
)

... rest of commands get echoed again

しかし、これを行うと、2つの問題が発生します。

  1. ユーザーに何かを言いたいときはいつでも書くべき量が多く、毎回説明が必要なほど「明らか」ではありません。
  2. set +xまた、これは望ましくないことを反映しています。

うまく動作する他のオプションはありますか?

それはまるで@Makeの機能は、エコーを抑えるために前に追加することです。それでいいのですが、Bashではそのような機能が見つかりませんでした。

答え1

Bashでは、次のようにこれを達成できます。いいえset -xキャプチャの代わりに使用DEBUGし、自己追跡を実行します。

#!/bin/bash

set -T

trap '! [[ "$BASH_COMMAND" =~ ^(echo|printf) ]] &&
      printf "+ %s\n" "$BASH_COMMAND"' DEBUG

foo=bar
echo This is a test
echo $foo
[[ $foo = bar ]] && /usr/bin/printf 'Matched\n'

アイデアは、その行の正規表現に無視したいコマンドを追加することですtrap。上記のコマンドを実行すると、次のようになります。

+ foo=bar
This is a test
bar
+ [[ $foo = bar ]]
+ /usr/bin/printf 'Matched\n'
Matched

set -Tトラップがシェル関数によって継承されていることを確認します。

トラップを有効または無効にする別のメカニズムを追加できます。例えばシェル変数を使用してください。

#!/bin/bash

set -T

status() {
        NOTRACE=1 echo "$@"
}

trap '! [[ "$BASH_COMMAND" =~ ^(status|NOTRACE=) ]] &&
      printf "+ %s\n" "$BASH_COMMAND"' DEBUG

foo=bar
test=$(echo baz)
echo This is a test
status This is a status report
echo $foo
[[ $foo = bar ]] && /usr/bin/printf 'Matched\n'

これは生産します

+ foo=bar
+ test=$(echo baz)
+ echo This is a test
This is a test
This is a status report
+ echo $foo
bar
+ [[ $foo = bar ]]
+ /usr/bin/printf 'Matched\n'
Matched

答え2

それはひどいクルーガーであり、それを提案するのは汚いと感じますが...あなたは使用することができます魔法のエイリアス。このトリックの鍵は、エイリアスがコマンド実行の解析フェーズの一部に拡張されるため、関数とは異なり、拡張時にset -x何も印刷されないことです。したがって、エイリアスを作成し、コマンドの前に「close -x」定型句を追加し、最後に「reopen」定型句を実行するecho関数も必要であることがわかります。-x

また、スクリプトでエイリアス拡張を有効にする必要があります。通常は無効になっているため、たとえばgrepエイリアスなどがある場合、grep --colorスクリプトで使用するたびにカラーコードはランダムに挿入されませんgrep。したがって、最も安全な方法は、最初にunalias -a実行して問題を引き起こす可能性があるエイリアスを削除することです。

とにかく、コードは次のようになります。

unalias -a
shopt -s expand_aliases
alias cleanecho='{ set +x; } 2>/dev/null; resetx_after echo'
resetx_after() { "$@"; set -x; }

set -x
cleanecho "Ha, ha, you can't see the command that printed this!"

仕組み:同様のコマンドが次にcleanecho "something"展開されます。

{ set +x; } 2>/dev/null; resetx_after echo "something"

{ set +x; } 2>/dev/nullオフ-xモード(セルフトレースを/ dev / nullにリダイレクト)し、次のコマンドをresetx_after echo "something"実行して実行します。

{ echo "something"; set -x; }

...文字列を印刷してから-xトレースをもう一度オンにします。

しかし、他のコマンドも同様に使用するには、printf同様のエイリアスを追加するだけです。

alias cleanprintf='{ set +x; } 2>/dev/null; resetx_after printf'

...または、プレフィックスとして使用する一般的なdon-trace-thisエイリアスを作成します。

alias notrace='{ set +x; } 2>/dev/null; resetx_after'
notrace printf 'set -x disabled for this command\n'

答え3

単純な。すでに半分くらい来たので、set -x近所に引っ越してください。

#!/bin/sh
echo a
(
    set -x
    echo b
)
echo c
$ a.sh
a
+ echo b
b
c

スクリプトの一部を追跡したくない場合は、2つの部分に分けて追跡してください。

#!/bin/sh
echo a
(
    set -x
    echo b
)
echo c
(
    set -x
    echo d
)
echo e

スクリプト全体ではなく、疑わしい部分だけを追跡してください。

関連情報