スクリプトの外部からbash実行トレース(-xを設定)を抑制します


17

私はこの質問に対する答えを見つけようとしましたが、今のところ運がありません。

他のスクリプトを実行するスクリプトがあり、それらのスクリプトの多くには「set -x」が含まれており、実行するすべてのコマンドが出力されます。それを取り除きたいのですが、スクリプトのいずれかがエラーメッセージをstderrに送信した場合は情報を保持します。

だから私は単に書くことはできません ./script 2>/dev/null

また、他のスクリプトを編集する権限がないため、設定オプションを手動で変更することはできません。

私はstderrから個別のファイルまですべてをログに記録し、トレースコマンドを除外することを考えていましたが、おそらくもっと簡単な方法がありますか?


1
./script 2>some_file
桂佐藤

回答:


25

bash4.1以上、あなたが行うことができます

BASH_XTRACEFD=7 ./script.bash 7> /dev/null

bashとして呼び出されたときにも機能しますsh)。

基本的に、デフォルトの2ではなくファイル記述子7に出力bashを出力し、xtraceそのファイル記述子をにリダイレクトするように指示しています/dev/null。fd番号は任意です。スクリプトで使用されていない2を超えるfdを使用します。あなたは、このコマンドを入力しているシェルがある場合bashまたはyash(ファイルディスクリプタは、シェルによって内部的に使用された場合に問題が発生したかもしれないが)、あなたも9の上に番号を使用することができます。

そのbashスクリプトを呼び出しているシェルがの場合zsh、次のこともできます。

(export BASH_XTRACEFD; ./script.bash {BASH_XTRACEFD}> /dev/null)

変数には、9を超える最初の空きfdが自動的に割り当てられます。

の古いバージョンではbash、別のオプションで、xtraceset -x#! /bin/bash -xまたはに対してset -o xtrace)でオンになっているset場合、渡されたときに何もしないエクスポートされた関数として再定義されます-x(ただし、スクリプト(またはbash呼び出す他のスクリプト)が破損する場合があります)set位置パラメータの設定に使用されます)。

お気に入り:

set()
  case $1 in
    (-x) return 0;;
    (-[!-]|"") builtin set "$@";;
    (*) echo >&2 That was a bad idea, try something else; builtin set "$@";;
  esac

export -f set
./script.bash

別のオプションは、すべてのコマンドの前に行う$BASH_ENVファイルにDEBUGトラップを追加することset +xです。

echo 'trap "{ set +x; } 2>/dev/null" DEBUG' > ~/.no-xtrace
BASH_ENV=~/.no-xtrace ./script.bash

set -xただし、サブシェルで実行された場合は機能しません。

@ilkkachuが言ったように、ファイルシステム上の任意のフォルダーへの書き込み権限がある場合、少なくともスクリプトのコピーを作成して編集できる必要があります。

スクリプトのコピーを作成できる場所がない場合、または元のスクリプトに更​​新があるたびに新しいコピーを作成および編集するのが不便な場合でも、次のことが可能です。

 bash <(sed 's/set -x/set +x/g' ./script.bash)

スクリプトが派手なもの$0や特別な変数$BASH_SOURCE(スクリプト自体の場所に関連するファイルの検索など)を行う場合、その(およびコピーアプローチ)は適切に機能しない可能性があるため、次のような編集が必要になる場合があります$0スクリプトのパスで置き換えます...


あなたの最初の答えは、まさに私が必要としていた、きれいでエレガントなものです。それがどのように機能するかを少し説明してもらえますか?なぜ7番?他の番号は何に使用できますか?ありがとう。
人間

@human、編集を参照
ステファンChazelas

1
この{BASH_XTRACEFD}>トリックはbash4.1以降でも機能します。
chepner

@chepner、はい、zsh開発者からの提案により、この機能はzsh、ksh93、およびbashに同時に追加されました。しかし、ここでは機能しないksh93か、bash変数が(compareコマンドの環境に渡されていないことで<shell> -c 'export fd; printenv fd {fd}> /dev/null'zshbashksh93)。あなたはそれがで動作させることができksh93/ bash2ステップでそれをやったり、おそらく使用することによってeval、しかしためbashXTRACEオプションがオンした場合の副作用を持っているであろうと、。
ステファンシャゼラス

5

彼らはスクリプトをしているので、あなたは可能性があり、それらのコピーを作成し、編集したもの。

それ以外は、出力のフィルタリングは単純に思えますがPS4、フィルタリングを簡単にするために、単一のプラスよりも異常なものを明示的に設定できます

PS4="%%%%" bash script.sh 2>&1 | grep -ve '^%%%%'

(もちろん、stdoutとstdinは折りたたまれますが、Bashでstderrだけをパイピングすると少し毛むくじゃらになるので、無視します)


1
stderrだけをパイピングするのは簡単ですPS4="%%%%" bash script.sh 2> >(grep -ve '^%%%%')
パトリック

4
@Patrick、それを非同期で実行するためbash問題がgrepあります(bashはそれを待っていないので、スクリプトの次のコマンドが開始された後に物事を出力できます(そしてしばしばします))。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.