実行時にシェルコマンドをエコーする方法


912

シェルスクリプトで、呼び出されたすべてのシェルコマンドをエコーし​​、変数名を展開するにはどうすればよいですか?

たとえば、次の行があるとします。

ls $DIRNAME

スクリプトでコマンドを実行して次を表示したい

ls /full/path/to/some/dir

目的は、呼び出されたすべてのシェルコマンドとその引数のログを保存することです。そのようなログを生成するより良い方法はおそらくありますか?

回答:


1043

set -x または set -o xtrace変数を展開し、行の前に小さな+記号を出力します。

set -vまたはset -o verbose、印刷前に変数を展開しません。

set +xおよびset +vを使用して、上記の設定をオフにします。

スクリプトの最初の行に、#!/bin/sh -x(または-v)を入れて、後のスクリプトset -x(または-v)と同じ効果を得ることができます。

上記はでも動作し/bin/shます。

set属性デバッグについては、bash-hackersのwikiを参照してください。

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$

7
実行されている番号付き行も確認したい場合は、stackoverflow.com
a / 17805088/1729501

3
コマンドとその結果出力を区別するためにエコーするときにコマンドに色を付けたい場合はどうなりますか?
ルイスチャン

11
ボーカロイドのような音声シンセサイザーでエコーするときに各コマンドを歌って、遠くから何をしているのかを聞いたり、音楽を楽しんだりするにはどうすればよいですか?おそらく、入力と出力で異なる音声を使用します。
ADJenks

(ABSは、彼らが悪い習慣の例を修正するという要求に応答せず、競合するリソースを作成するように長年のコミュニティメンバーを駆り立てるまでの長い歴史を持っています; bash-hackers 'wiki-Wooledge wikiまたは公式のbashマニュアル参考になります)。
Charles Duffy

317

set -x あなたが望むものをあなたに与えるでしょう。

デモ用のシェルスクリプトの例を次に示します。

#!/bin/bash
set -x #echo on

ls $PWD

これにより、すべての変数が展開され、コマンドの出力前に完全なコマンドが出力されます。

出力:

+ ls /home/user/
file1.txt file2.txt

21
このように「冗長」という言葉を使用しても、何も起こりません。あなたは行うことができますset -o verboseset -v(唯一の「冗長」)またはset -o xtraceまたはset -x(のみ「XTRACE」)またはset -xv(両方)またはset -o xtrace -o verbose(両方)。
追って通知があるまで一時停止。

これは適切に機能しますが、「冗長」が$ 1を上書きすることに注意してください
JasonS

90

関数を使用してコマンドをエコーし​​、実行します。

#!/bin/bash
# Function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

どの出力

$ echo hello world
hello world

より複雑なコマンドパイプなどの場合は、evalを使用できます。

#!/bin/bash
# Function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello, World!' | cut -d ' ' -f1"

どの出力

$  echo 'Hello, World!' | cut -d ' ' -f1
Hello

この回答に対する投票は多くありません。それが悪い考えである理由はありますか?私のために働いた、そしてまさに私が探しているもののように思われる...
fru1tbat '22

1
すべてのコマンドを出力したくない場合は、これが最良の答えです。++ set +xオフにすると出力が回避され、見た目もきれいになります。ただし、1つまたは2つのステートメントでは、サブシェルを使用したbhasselの答えが最も便利です。
ブレントファウスト

これは私が探しているものです!そうではなくset +x、すべてのコマンドに影響します。
Hlung

11
これの主な欠点は、出力が引用情報を失うことです。あなたは区別することはできませんcp "foo bar" bazし、cp foo "bar baz"例えば、。したがって、進行状況の情報をユーザーに表示するのに適しています。出力のデバッグや再現可能なコマンドの記録にはそれほど役立ちません。さまざまなユースケース。ではzsh、あなたが引用し保存することができ:q修飾子:exe() { echo '$' "${@:q}" ; "$@" ; }
アンドリュー・ジャンキ

2
この答えは好きではありません。表示されるものが得られるものとは異なる多くのエッジケースがあります(特に空白、引用符、エスケープ文字、変数/式の置換などで)、エコーされたコマンドを盲目的にターミナルに貼り付けて、実行されると想定しないでください同じ方法。また、2番目の手法は単なるハックでありeval、コマンドから単語の他のインスタンスを削除します。だから、それが正しく動作することを期待しないでexe eval "echo 'eval world'"ください!
mwfearnley

88

set -xまたset +x、次のようにラップして、スクリプト内の選択した行のこれを切り替えることもできます。

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi

54

選択行をエコーするためのshuckcの回答にはいくつかの欠点があります。次のset +xコマンドもエコーされることになり、終了コード$?がによって上書きされるため、終了コードをテストできなくなりますset +x

別のオプションは、サブシェルでコマンドを実行することです:

echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )

if [ $? -eq 0 ] ; then
    echo "curl failed"
    exit 1
fi

次のような出力が得られます:

getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed

ただし、これにより、コマンドの新しいサブシェルを作成するオーバーヘッドが発生します。


7
++ set +x出力を回避するための素晴らしい方法。
ブレントファウスト

3
さらに良い:置き換えるif [ $? -eq 0 ]if (set -x; COMMAND)
Amedee Van Gasse 2017年

35

別のオプションは、コマンドラインではなく、スクリプトの先頭に「-x」を置くことです。

$ cat ./server
#!/bin/bash -x
ssh user@server

$ ./server
+ ssh user@server
user@server's password: ^C
$

まったく同じの間、これが動作するようには思えないことに注意./myScriptしてbash myScript。まだ指摘しておくべき良いこと、ありがとう。
altendky 2015

27

TLDP初心者向けBashガイドによると:第2章スクリプトの作成とデバッグ

2.3.1。スクリプト全体のデバッグ

$ bash -x script1.sh

...

SourceForgeで利用可能なBash用の本格的なデバッガーが利用可能になりました。これらのデバッグ機能は、3.x以降のほとんどの最新バージョンのBashで使用できます。

2.3.2。スクリプトの一部のデバッグ

set -x            # Activate debugging from here
w
set +x            # Stop debugging from here

...

表2-1。設定されたデバッグオプションの概要

    Short  | Long notation | Result
    -------+---------------+--------------------------------------------------------------
    set -f | set -o noglob | Disable file name generation using metacharacters (globbing).
    set -v | set -o verbose| Prints shell input lines as they are read.
    set -x | set -o xtrace | Print command traces before executing command.

...

または、最初の行のシェル宣言に必要なオプションを追加することにより、スクリプト自体でこれらのモードを指定できます。UNIXコマンドの場合は通常そうであるように、オプションを組み合わせることができます。

#!/bin/bash -xv

18

コマンドラインで、Bashスクリプトの名前の前に「bash -x」と入力します。たとえば、foo.shを実行するには、次のように入力します。

bash -x foo.sh

11

オプションを使用して、デバッグモードでBashスクリプトを実行でき-xます

これにより、すべてのコマンドがエコーされます。

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

スクリプトに-xオプションを保存することもできます-xシバンでオプションを指定するだけです。

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

2
またbash -vx、同じことを行いますが、変数補間は行いません
loa_in_

4

zshの場合、echo

 setopt VERBOSE

そしてデバッグのために、

 setopt XTRACE

2

以下のためにcshtcsh、することができますset verboseset echo(あるいはあなたも、両方を設定することができますが、それはほとんどの時間のいくつかの重複が生じる場合があります)。

verboseオプションは、入力したシェル式をほぼ正確に出力します。

このechoオプションは、スポーンによって実行される内容をより詳しく示しています。


http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo


Special shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.



1

複合コマンドをエコーできるようにするには、evalplus Sothのexe機能を使用してコマンドをエコーし​​、実行します。これは、パイプされたコマンドの何も表示しないか、パイプされたコマンドの最初の部分のみを表示するパイプコマンドに役立ちます。

評価なし:

exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt

出力:

$
file.txt

評価あり:

exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'

どの出力

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