印刷せずにBashセット+ x


92

set +x印刷せずにbashで言うことができるかどうか誰かが知っていますか:

set -x
command
set +x

痕跡

+ command
+ set +x

しかし、それは単に印刷する必要があります

+ command

Bashはバージョン4.1.10(4)です。これはしばらくの間私を悩ませています-出力が無駄なset +x行で乱雑になり、トレース機能がそれ程有用ではなくなります。


これはあなたの質問の答えにはなりませんが、スクリプトを実行するとなぜそうならないのですか?script.sh 2>&1 | grep -v 'set +x'
cdarke

回答:


145

同じ問題があり、サブシェルを使用しない解決策を見つけることができました。

set -x
command
{ set +x; } 2>/dev/null

10
すばらしい回答、ただのメモ:コマンドの後にセミコロンがないと、これは機能しません。セミコロンを使用しますが、中括弧にスペースを入れないと、構文エラーが発生します。
sdaau 2014

9
これにより、終了ステータスがゼロになります。
Garth Kidd

8
@GarthKidd終了ステータスは、コマンドが成功するたびにゼロになります。set +xこのような成功したコマンドです
ダニエル・アルダー

3
の終了ステータスが必要な場合はcommand、このバリエーションが解決策です{ STATUS=$?; set +x; } 2>/dev/null。その後$STATUS、余暇に次のラインで検査してください。
グレッグ価格

5
これとは別に、少し先のバージョンは次のとおり{ set +x; } 2>&-です。これは、/ dev / nullを指すのではなく、fd 2を完全に閉じます。一部のプログラムは、stderrに出力しようとしたときにそれをうまく処理しません。そのため、/ dev / nullは一般的に優れたスタイルです。しかし、シェルのset -xトレースはそれをうまく処理するので、ここで完全に機能し、この呪文を少し短くします。
グレッグ価格

43

サブシェルを使用できます。サブシェルを終了すると、設定xが失われます:

( set -x ; command )

まあ、ありがとう...良い点。実は私は「サブシェルトリック」を知っています。それよりも簡単だと思いました。これにはコードの大幅な変更が含まれるため、コードが複雑になり、読みにくくなります。+ x行のセットで生活するよりも悪いであろう私見...
Andreas Spindler

どの( set -x \n command \n )ように悪いのかはわかりませんset -x \n command \n set +x
chepner

3
@chepner:変数を設定することはできません。
チョロバ

2
...そしてできませんcd:親シェルの現在のディレクトリは変更されません。
アンドレアススピンドラー

申し訳ありませんが、あなたの実際の異論が何だったのかはわかりません。長い週
でした

8

私はこれに悩まされたときに、この問題の解決策を最近作りました:

shopt -s expand_aliases
_xtrace() {
    case $1 in
        on) set -x ;;
        off) set +x ;;
    esac
}
alias xtrace='{ _xtrace $(cat); } 2>/dev/null <<<'

これにより、次のようにxtraceを有効または無効にできます。ここでは、引数が変数に割り当てられる方法をログに記録しています。

xtrace on
ARG1=$1
ARG2=$2
xtrace off

そして、次のような出力が得られます。

$ ./script.sh one two
+ ARG1=one
+ ARG2=two

巧妙なトリック(/dev/stdin一部は必要ありませんが)。注意点として、スクリプトでエイリアス展開を有効にすると、望ましくない副作用が生じる可能性があります。
mklement0 2014

あなたが正しい。不要なものを削除するために回答を編集しました/dev/stdin。非インタラクティブ環境ではエイリアスを定義するファイルをロードしないため、特定の副作用については知りません。どのような副作用がありますか?
user108471 14

1
それは良い点です-エイリアスが継承されないことを忘れていたので、リスクは思ったよりもはるかに小さいです(仮に、スクリプトがエイリアスを定義するサードパーティのコードを調達している可能性がありますが、それはおそらく現実的ではありません-世界の懸念)。+1
mklement0 2014

1
@AndreasSpindlerこの手法がより機密性の高い情報を漏らす可能性が高いと思う理由を詳しく説明していただけますか?
user108471 2015年

1
...基本的には、エイリアスと関数は高レベルの構造だからです。set +x妥協するのは(不可能ではないにしても)はるかに難しい。しかし、それは依然として優れた真っ直ぐな解決策です-おそらくこれまでのところ最良の解決策です。
Andreas Spindler 2015

7

@ user108471の簡易バージョンに基づくソリューションはどうですか?

shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ set +x; } 2>/dev/null'

trace_on
...stuff...
trace_off

これはどう?function () { set_plus_x='{ set +x; } 2>/dev/null' }
LexH 2018

1

これは、コードのブロックを囲み、終了ステータスを保持するいくつかのアイデアの組み合わせです。

#!/bin/bash
shopt -s expand_aliases
alias trace_on='set -x'
alias trace_off='{ PREV_STATUS=$? ; set +x; } 2>/dev/null; (exit $PREV_STATUS)'

trace_on
echo hello
trace_off
echo "status: $?"

trace_on
(exit 56)
trace_off

実行すると:

$ ./test.sh 
+ echo hello
hello
status: 0
+ exit 56
status: 56

いい努力ですが、()周りexitは必要ないと思います。OK。たぶんの偏執的でなく、このコードは、一般的に使用されている場合、あなたは良い攻撃ベクトル持っている:再定義trace_ontrace_offして実行されたコマンドを読み込みジェクトコードを。そのような「ユーティリティ」を単独で使用する場合、それは有益ですが、コードが他の人と一緒に使用される場合、そのような非標準化された関数の利点が欠点を上回るかどうかを考慮する必要があります。{ set +x; } 2>/dev/nullこの構成は一般的に理解されており、終了ステータスも変更しないため、個人的には解決しました。
Andreas Spindler
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.