標準出力を中断せずにbash -x出力をログファイルに送信します


12

スクリプトを実行しているユーザーに表示される標準出力を変更せずに、-xオプションを指定してbashスクリプトを実行することで表示される情報を送信する方法はありますか?

これは、頻繁に使用するbashスクリプトで実装したいデバッグ機能です。

大変感謝いたします。

回答:


21

-xからの出力は、stdoutではなくstderrに送られます。しかし、それでも問題になる可能性があります。多くのスクリプトはstderrのコンテンツに機能的に依存し、場合によってはデバッグストリームとstderrストリームを混在させるのが面倒です。

Bashバージョン4.1以降では、別のソリューションが提供されます。BASH_XTRACEFD環境変数を使用すると、デバッグストリームの送信に使用されるファイル記述子を指定できます。これは、ファイルまたはパイプ、またはその他のUNIXの良さです。

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

もう少し手間をかけることで、stdoutやstdinストリームで「ティー」を実行するなど、他のことを行うことができ、それらをデバッグ出力でインターリーブするため、ログがより完全になります。詳細については、https://stackoverflow.com/questions/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itselfを参照してください

代替手段に対するこのアプローチの大きな利点は、デバッグ出力をstdoutまたはstderrに挿入することにより、スクリプトの動作を変更するリスクがないことです。


ファイルの未使用のファイル記述子を見つける方法については、こちらも参照してください。
ジャーノ

ファイル記述子を閉じる必要がありますexec 19>&-か(行)。私の経験では、スクリプトが終了すると自動的に閉じられます。
ジャーノ

1
上記のコードは、スクリプトを実行していることや、スクリプトの長さなどを想定していません。このスニペットがしていることを実行して、スクリプトにそれを入れると、ファイルハンドルはスクリプトの最後でシェル全体が消えるという理由だけで閉じられます。そのため、このユースケースでは、ハンドルを厳密に閉じる必要はありません。しかし、一般的にリソースに対してコーディングするときは、開いたものを閉じることをお勧めします。ハウスキーピングが重要になる可能性のあるより大きなコンテキストでコードを使用できるからです。
ステーブルドッグ

なぜBASH_XTRACEFDをエクスポートするのですか?なぜ値を設定しないのですか?
ジャーノ

とにかく、ファイル記述子を閉じる別の方法は、BASH_XTRACEFDに新しい値(たとえばnull)を設定するか、設定解除することです。
ジャーノ

4

set -x標準出力には何も送信されないため、問題はありません。それがすることは標準エラーへの書き込みで、デフォルトでコンソールに行きます。

次のように、stdoutを別のファイルにリダイレクトします。

/bin/sh -x /my/script/file 2>/my/log/file

1

をご覧くださいman tee

次のように実行するtee commandname filenameと、コマンド出力が表示され、stdoutにも書き込まれfilenameます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.