シェルスクリプトで、呼び出されたすべてのシェルコマンドをエコーし、変数名を展開するにはどうすればよいですか?
たとえば、次の行があるとします。
ls $DIRNAME
スクリプトでコマンドを実行し、次のように表示したいのですが
ls /full/path/to/some/dir
目的は、呼び出されたすべてのシェルコマンドとその引数のログを保存することです。そのようなログを生成するためのより良い方法はおそらくありますか?
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
$
set -x
あなたが望むものをあなたに与えるでしょう。
以下に、デモンストレーション用のシェルスクリプトの例を示します。
#!/bin/bash
set -x #echo on
ls $PWD
これにより、すべての変数が展開され、コマンドの出力前に完全なコマンドが出力されます。
出力:
+ ls /home/user/
file1.txt file2.txt
関数を使用して、コマンドをエコーして実行します。
#!/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
スクリプト内の選択した行をラップして、たとえば、これを切り替えることもでき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
選択行をエコーするための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
ただし、これには、コマンドの新しいサブシェルを作成するオーバーヘッドが発生します。
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
もう1つのオプションは、コマンドラインではなくスクリプトの先頭に「-x」を配置することです。
$ cat ./server
#!/bin/bash -x
ssh user@server
$ ./server
+ ssh user@server
user@server's password: ^C
$
オプションを使用して、デバッグモードで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
コマンドラインでBashスクリプトの名前の前に「bash-x」と入力します。たとえば、foo.shを実行するには、次のように入力します。
bash -x foo.sh
すべての答えを組み合わせると、これが最良で最も単純であることがわかりました
# https://stackoverflow.com/a/64644990/8608146
exe(){
set -x
"$@"
{ set +x; } 2>/dev/null
}
# example
exe go generate ./...
{ set +x; } 2>/dev/null
https://stackoverflow.com/a/19226038/8608146から
ここで説明するように、コマンドの終了ステータスが必要な場合
使用する
{ STATUS=$?; set +x; } 2>/dev/null
そして最後の$STATUS
ように後者を使用してくださいexit $STATUS
もう少し便利なもの
# https://stackoverflow.com/a/64644990/8608146
_exe(){
[ $1 == on ] && { set -x; return; } 2>/dev/null
[ $1 == off ] && { set +x; return; } 2>/dev/null
echo + "$@"
"$@"
}
exe(){
{ _exe "$@"; } 2>/dev/null
}
# examples
exe on # turn on same as set -x
echo This command prints with +
echo This too prints with +
exe off # same as set +x
echo This does not
# can also be used for individual commands
exe echo what up!
zshの場合、echo
setopt VERBOSE
そしてデバッグのために、
setopt XTRACE
複合コマンドをエコーできるようにするために、eval
plusSothの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
csh
およびの場合、またはを使用tcsh
できます(または、両方を設定することもできますが、ほとんどの場合、重複が発生する可能性があります)。set verbose
set 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.