bashスクリプトをデバッグする方法は?


135

エラーと予期しない動作について、bashの一部のスクリプトに問題があります。修正を適用できるように、問題の原因を調査したいと思います。より多くの情報を取得するために、bashで何らかの「デバッグモード」を有効にする方法はありますか?

回答:


132

デバッグ出力を表示bash -x ./script.shするには、bashスクリプトを開始するか、スクリプトset -xを追加します。


bash4.1以降で追加:

デバッグ出力を別のファイルに書き込む場合は、これをスクリプトに追加します。

exec 5> debug_output.txt
BASH_XTRACEFD="5"

参照:https : //stackoverflow.com/a/25593226/3776858


行番号を見たい場合は、これを追加してください:

PS4='$LINENO: '


loggerコマンドに アクセスできる場合、これを使用して、タイムスタンプ、スクリプト名、および行番号を使用してsyslogを介してデバッグ出力を書き込むことができます。

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here

コマンドのオプション-pを使用しloggerて個々の機能とレベルを設定し、ローカルsyslogを介して出力を独自のログファイルに書き込むことができます。


7
-vも役立ちます(実行されると各行を出力します。-xと組み合わせることができます)。また参照してください:bashdb.sourceforge.net
オリビエデュラック

4
別の素晴らしいリソースは:shellcheck.net
オリビエデュラック

「exec 5>」は何をしますか?
aggsol

3
@aggsol:BASH_XTRACEFD="5"bash を使用する場合set -x、有効になっているときに生成されたトレース出力をファイル記述子 5に書き込みますexec 5> >(logger -t $0)ファイル記述子5からの出力をloggerコマンドにリダイレクトします。
サイラス

1
PS4で行番号とシェルスクリプトのパスまたは名前を取得できますか?
-iloveretards

55

を使用して set -x

私は常にとを使用set -xset +xます。あなたは、冗長性を上下に変えるためにそれらで何が起こっているかを見たい領域をラップすることができます。

#!/bin/bash

set -x
..code to debug...
set +x

log4bash

また、開発作業を完了し、log4j、log4perlなどの名前のロガーのスタイルに精通している場合は、log4bashを使用することもできます。

抜粋

それに直面しましょう-単純な古いエコーはそれをカットしません。log4bashは、Bashスクリプトのロギングを改善するための試みです(つまり、Bashのロギングを少なくします)。

そこから、Bashスクリプトで次のようなことができます。

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

このタイプの出力になります:

    ss1

log4sh

よりポータブルなものが必要な場合は、古いバージョンもありlog4shます。に類似した動作log4bash、ここから入手可能:


Ubuntuでは、私が持っているalias say="spd-say"模倣私の.bashrcにsay他のディストリビューションやOS Xからコマンドを
ドアノブ

1
set -vxは、trap-trap read debugとともに使用する場合に適切な組み合わせです。これは、あなたは行ずつステップオーバーして結果を確認することができます
マグナスMelwin

34

bashデバッガーbashdbがあります。これは多くのディストリビューションにインストール可能なパッケージです。bashの組み込み拡張デバッグモード(shopt -s extdebug)を使用します。gdbによく似ています。ここにいくつかの風味を与えるためのサンプルセッションがあります:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf

gdbの場合と同様に、ステートメントは実行される直前表示されます。そのため、変数を調べて、ステートメントが実行する前に実行する内容を確認できます。

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG

それは私たちが望むものではありません!もう一度パラメータ展開を見てみましょう。

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg

OK newf正しい値に設定しましょう。

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

いいね。スクリプトを続行します。

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg

20

bashなど、ほとんどのBourneベースのシェルでスクリプトをデバッグする標準的な方法set -xは、スクリプトの先頭に記述することです。これにより、bashは実行/実行されていること、および引数の評価方法についてより詳細になります。

-x  Print commands and their arguments as they are executed.

これは、インタプリタまたは内部スクリプトのいずれかに役立ちます。例えば:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory

上記で、単一引用符が原因でfindが失敗する理由を確認できます。

機能を無効にするには、単に入力しset +xます。


13

Eclipseを使用する

以下にリンクされている「_DEBUG.sh」スクリプトを使用して、EclipseとShelledの複合環境を使用できます。

シェルの切り替え

デフォルトでは、Shelled開発ツールは/bin/dashインタープリターとして使用します。これを変更/bin/bashして、Webおよび私の環境のほとんどのシェル例との互換性を高めました。

注:これを変更するには、[ ウィンドウ] -> [ 設定] -> [ シェルスクリプト] -> [ インタープリター]に移動します。

セットアップ手順

Debuggerパッケージには、_DEBUG.sh基本的に(readme.txt)であるスクリプトデバッグ用のスクリプトを使用するための手順が含まれています。

  1. シェルスクリプトプロジェクトの作成: ファイル -> 新規 -> その他 -> シェルスクリプト -> シェルスクリプトプロジェクトウィザード
  2. bashスクリプトファイルを作成します。ファイル - > 新規作成 - > ファイル。この例では、になりますscript.sh。拡張子は「.sh」である必要があります。
  3. ファイル_DEBUG.shをプロジェクトフォルダーにコピーします。
  4. ファイルの先頭に次のテキストを挿入しますscript.sh

    . _DEBUG.sh
  5. ファイルがMicrosoft Windowsで作成されている場合は、必ず[ファイル] -> [ 行区切り文字の変換] -> [ Unix ]を実行してください。

  6. デバッグ起動構成を設定します。実行 -> デバッグ構成 -> Bashスクリプト...ここに設定する2つのフィールドがあります。

    a)「Bashスクリプト:」-Eclipseのワークスペース内のデバッグするBashスクリプトへのパス。
    e) "デバッガーポート:" 33333

  7. [デバッグ]パースペクティブに切り替えます。デバッグセッションを開始します。script.shbashシェルから起動します。

bashデバッグUI

ここに画像の説明を入力してください

このbashデバッガーには、次のような標準プログラミングデバッガーの完全な機能があります。

  • ブレークポイント切り替え
  • シングルステップバイステップ操作
  • ステップイン、ステップアウト、ステップオーバー機能およびサブルーチン
  • スクリプトの実行中の任意の時点でコードまたは変数を調べる

Shelled(Shell Script Editor)IDE(統合開発環境)には、スクリプトの作成中にコンテキストチェック、強調表示、インデントを実行するというボーナスが追加されています。正しくインデントされない場合、すぐに多くのエラーにフラグを付けたり、ローカルにしたりすることができます。

次に、次のような他のIDEの利点があります。

  • TODOタスクリスト
  • マイリンタスク
  • ブックマークリスト
  • 複数ウィンドウの編集
  • 環境のリモート共有

クールなヒント。Bashはこのようにデバッグできることを知ってうれしいです。
slm

8

近年、素晴らしいリソースが登場しました:http : //shellcheck.net

通常のbashよりも多くの情報が表示されるため、厄介な閉じていない引用符や中括弧などを簡単に見つけることができます。

ネット上に機密情報(IP、パスワードなど)を貼り付けないようにしてください(特にhttpで暗号化されていないため)(shellcheckもダウンロードできると思いますが、わかりません)


6

単に使用します:

#!/bin/bash -x

シェルについても同じ:

#!/bin/sh -x

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