bashスクリプトをデバッグする方法はありますか?たとえば、「calling line 1」、「calling line 2」などのような実行ログを出力するものです。
bashスクリプトをデバッグする方法はありますか?たとえば、「calling line 1」、「calling line 2」などのような実行ログを出力するものです。
回答:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
これらは、実行中のトレースを提供します。(回答の下部にある「説明」も参照してください。)
場合によっては、スクリプト内でデバッグを制御する必要があります。その場合、チート が私に思い出させたように、あなたは使うことができます:
set -x
これにより、デバッグがオンになります。その後、次のコマンドでオフにできます。
set +x
($-
現在のフラグを分析することにより、現在のトレース状態を確認できます。x
。)
また、シェルは通常-n
、「実行なし」のオプション「-v
」と「冗長」モードのオプション「」を提供します。これらを組み合わせて使用することで、シェルがスクリプトを実行できるとシェルが判断したかどうかを確認できます。
-x
Bashの' 'オプションは他のシェルとは異なるという意見があります(コメントを参照)。Bashのマニュアルは言います:
-バツ
単純なコマンド、for
コマンド、case
コマンド、select
コマンド、および算術for
コマンドと、それらの引数または関連する単語リストのトレースを、それらが展開されてから実行される前に出力します。PS4
変数の値が展開され、結果の値がコマンドとその展開された引数の前に出力されます。
それだけではまったく異なる動作を示しているようには見えません。-x
マニュアルに他の「」への参照がありません。起動シーケンスの違いについては説明しません。
明確化:「/bin/sh
」が「」へのシンボリックリンクである典型的なLinuxボックスなどのシステム/bin/bash
(またはBash実行可能ファイルが検出された場所)では、2つのコマンドラインは、実行トレースをオンにしてスクリプトを実行するのと同等の効果を実現します。他のシステム(たとえば、Solaris、およびLinuxの最新のバリアント)では、/bin/sh
Bashではないため、2つのコマンドラインは(わずかに)異なる結果をもたらします。最も注目すべきは、 ' /bin/sh
'がまったく認識されないBashの構成要素と混同されることです。(Solarisでは/bin/sh
、Bourneシェルです。最新のLinuxでは、Dashになることがあります。これは、より小さく、厳密にはPOSIXのみのシェルです。)このような名前で呼び出されると、 'shebang'行( ' #!/bin/bash
' vs '#!/bin/sh
'
BashのマニュアルにはBash POSIXモードに関するセクションがあり、この回答の長い間誤ったバージョン(以下のコメントも参照)とは異なり、「Bashが呼び出されたsh
」と「Bashが呼び出された」の違いについて詳しく説明していますbash
'。
(Bash)シェルスクリプトをデバッグするときは、-x
オプションを指定してシバン行で指定されたシェルを使用することが賢明であり、正気です。そうしないと、デバッグ時とスクリプト実行時の動作が異なる可能性があります(?)。
bash
スクリプトを指定しました。でbashスクリプトを実行するsh -x
と、動作がまったく異なります!回答を更新してください。
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
次の方法でスクリプトをデバッグしました。
set -e
外部プログラムがゼロ以外の終了ステータスを返した場合、スクリプトをすぐに停止させます。これは、スクリプトがすべてのエラーケースを処理しようとする場合、および処理の失敗をトラップする必要がある場合に役立ちます。
set -x
は前述したとおり、すべてのデバッグ方法の中で最も有用です。
set -n
スクリプトの構文エラーをチェックする場合にも役立ちます。
strace
何が起こっているかを確認するのにも役立ちます。スクリプトを自分で作成していない場合に特に便利です。
strace -f
スクリプトによって開始されたプロセスのエラーも検出したい場合は、これが必要であることに注意してください。(これにより何倍も冗長になりますが、興味のあるシステムコールに限定すればなお便利です)。
set -e
は... 物議を醸す。
この回答は有効で便利です:https : //stackoverflow.com/a/951352
しかし、「標準的な」スクリプトのデバッグ方法は非効率的で直感的ではなく、使いにくいことがわかりました。すべてをあなたの指先に置き、簡単な問題(そして難しい問題の可能性)のために仕事を簡単にする洗練されたGUIデバッガに慣れている人にとって、これらのソリューションはあまり満足のいくものではありません。
私がしていることは、DDDとbashdbを組み合わせて使用することです。前者は後者を実行し、後者はスクリプトを実行します。これにより、マルチウィンドウUIにコンテキスト内のコードをステップ実行し、変数やスタックなどを表示する機能が提供されます。頭の中でコンテキストを維持したり、ソースを再リストしたりするための一定の精神的な努力は必要ありません。
これを設定するためのガイダンスがあります:http : //ubuntuforums.org/showthread.php?t=660223
私はshellcheckユーティリティを見つけました、そしてそれが興味深いhttps://github.com/koalaman/shellcheckだと思う人もいるかもしれません
小さな例:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
バグを修正し、最初に試してください...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
もう一度やってみましょう...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
今見つけて!
ほんの小さな例です。
プラグインシェルとbasheclipseでeclipseを使用します。
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
シェルの場合:zipをダウンロードして、ヘルプを介してEclipseにインポートします->新しいソフトウェアをインストールします:ローカルアーカイブbasheclipseの場合:jarをeclipseのdropinsディレクトリにコピーします
手順に従ってくださいhttps://sourceforge.net/projects/basheclipse/files/?source=navbar
多くのスクリーンショットを含むチュートリアルをhttp://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.htmlで書きました
Bashデバッガーをビルドしました。試してみてください。それがhttps://sourceforge.net/projects/bashdebugingbashに役立つことを願ってい ます
+ x = @ECHO OFFを設定し、-x = @ECHO ONを設定します。
-xv
次のように、オプションを標準シバンに追加できます。
#!/bin/bash -xv
-x
:実行時にコマンドとその引数を表示します。
-v
:読み取られたシェル入力行を表示します。
ltrace
は、に似た別のLinuxユーティリティstrace
です。ただし、ltrace
実行可能ファイルまたは実行中のプロセスで呼び出されているすべてのライブラリ呼び出しをリストします。その名前自体は、ライブラリ呼び出しトレースに由来しています。例えば:
ltrace ./executable <parameters>
ltrace -p <PID>
私はあなたがこのBashデバッガを試すことができると思います:http : //bashdb.sourceforge.net/。
set -[nvx]
に加えて
set -x
そして
set +x
ダンプを停止します。
set -v
ダンプが小さいほど、出力が大きくならないことについてお話します。
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
いくつかの変数をテストするために、私はいつかこれを使用します:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
追加用:
declare >&2 -p var1 var2
18行目で、スクリプトを実行し(argsを使用)、編集する必要はありません。
もちろん、これを追加するために使用できますset [+-][nvx]
:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
declare -p v1 v2 >&2
18行目以降、set -x
22行目前、set +x
26行目前に追加されます。
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
注:ケアについて$LINENO
の影響を受けることになるオンザフライで変更を!
(実行中の結果のスクリプトを確認するには、単にドロップbash <(
して) arg1 arg2
)
シェルのグローバル変数を介したシェルスクリプトのロギングについては、かなりの詳細があります。シェルスクリプトで同様の種類のロギングをエミュレートできます。http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
この投稿には、INFO、DEBUG、ERRORなどのログレベルの紹介に関する詳細があります。スクリプトのエントリ、スクリプトの終了、関数のエントリ、関数の終了などの詳細のトレース。
サンプルログ: